diff --git a/src/doc/reference.md b/src/doc/reference.md index 3bbe60a77c9..db940947040 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -572,7 +572,7 @@ the final namespace qualifier is omitted. Two examples of paths with type arguments: ``` -# struct HashMap; +# struct HashMap(K,V); # fn f() { # fn id(t: T) -> T { t } type T = HashMap; // Type arguments used in a type expression @@ -1599,7 +1599,7 @@ pointer values (pointing to a type for which an implementation of the given trait is in scope) to pointers to the trait name, used as a type. ``` -# trait Shape { } +# trait Shape { fn dummy(&self) { } } # impl Shape for i32 { } # let mycircle = 0i32; let myshape: Box = Box::new(mycircle) as Box; @@ -1630,8 +1630,8 @@ let x: f64 = Num::from_i32(42); Traits may inherit from other traits. For example, in ``` -trait Shape { fn area() -> f64; } -trait Circle : Shape { fn radius() -> f64; } +trait Shape { fn area(&self) -> f64; } +trait Circle : Shape { fn radius(&self) -> f64; } ``` the syntax `Circle : Shape` means that types that implement `Circle` must also @@ -1725,7 +1725,7 @@ type parameters taken by the trait it implements. Implementation parameters are written after the `impl` keyword. ``` -# trait Seq { } +# trait Seq { fn dummy(&self, _: T) { } } impl Seq for Vec { /* ... */ } diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 4cd3d587580..b43f9adfb26 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -96,7 +96,7 @@ pub struct Arena<'longer_than_self> { head: RefCell, copy_head: RefCell, chunks: RefCell>, - _invariant: marker::InvariantLifetime<'longer_than_self>, + _marker: marker::PhantomData<*mut &'longer_than_self()>, } impl<'a> Arena<'a> { @@ -111,7 +111,7 @@ impl<'a> Arena<'a> { head: RefCell::new(chunk(initial_size, false)), copy_head: RefCell::new(chunk(initial_size, true)), chunks: RefCell::new(Vec::new()), - _invariant: marker::InvariantLifetime, + _marker: marker::PhantomData, } } } @@ -361,6 +361,8 @@ pub struct TypedArena { } struct TypedArenaChunk { + marker: marker::PhantomData, + /// Pointer to the next arena segment. next: *mut TypedArenaChunk, diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index c6cd6895728..7823f536c7a 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -512,13 +512,22 @@ mod stack { use super::super::node::handle; use vec::Vec; + struct InvariantLifetime<'id>( + marker::PhantomData<::core::cell::Cell<&'id ()>>); + + impl<'id> InvariantLifetime<'id> { + fn new() -> InvariantLifetime<'id> { + InvariantLifetime(marker::PhantomData) + } + } + /// A generic mutable reference, identical to `&mut` except for the fact that its lifetime /// parameter is invariant. This means that wherever an `IdRef` is expected, only an `IdRef` /// with the exact requested lifetime can be used. This is in contrast to normal references, /// where `&'static` can be used in any function expecting any lifetime reference. pub struct IdRef<'id, T: 'id> { inner: &'id mut T, - marker: marker::InvariantLifetime<'id> + _marker: InvariantLifetime<'id>, } impl<'id, T> Deref for IdRef<'id, T> { @@ -560,7 +569,7 @@ mod stack { pub struct Pusher<'id, 'a, K:'a, V:'a> { map: &'a mut BTreeMap, stack: Stack, - marker: marker::InvariantLifetime<'id> + _marker: InvariantLifetime<'id>, } impl<'a, K, V> PartialSearchStack<'a, K, V> { @@ -595,11 +604,11 @@ mod stack { let pusher = Pusher { map: self.map, stack: self.stack, - marker: marker::InvariantLifetime + _marker: InvariantLifetime::new(), }; let node = IdRef { inner: unsafe { &mut *self.next }, - marker: marker::InvariantLifetime + _marker: InvariantLifetime::new(), }; closure(pusher, node) diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs index 8f5ee35fcb2..f0fc12da727 100644 --- a/src/libcollections/btree/node.rs +++ b/src/libcollections/btree/node.rs @@ -20,10 +20,11 @@ use core::prelude::*; use core::cmp::Ordering::{Greater, Less, Equal}; use core::iter::Zip; +use core::marker::PhantomData; use core::ops::{Deref, DerefMut, Index, IndexMut}; use core::ptr::Unique; use core::{slice, mem, ptr, cmp, num, raw}; -use alloc::heap; +use alloc::heap::{self, EMPTY}; use borrow::Borrow; @@ -58,8 +59,8 @@ pub struct Node { keys: Unique, vals: Unique, - // In leaf nodes, this will be null, and no space will be allocated for edges. - edges: Unique>, + // In leaf nodes, this will be None, and no space will be allocated for edges. + edges: Option>>, // At any given time, there will be `_len` keys, `_len` values, and (in an internal node) // `_len + 1` edges. In a leaf node, there will never be any edges. @@ -279,8 +280,11 @@ impl Drop for RawItems { #[unsafe_destructor] impl Drop for Node { fn drop(&mut self) { - if self.keys.ptr.is_null() { - // We have already cleaned up this node. + if self.keys.is_null() { + // Since we have #[unsafe_no_drop_flag], we have to watch + // out for a null value being stored in self.keys. (Using + // null is technically a violation of the `Unique` + // requirements, though.) return; } @@ -293,7 +297,7 @@ impl Drop for Node { self.destroy(); } - self.keys.ptr = ptr::null_mut(); + self.keys = unsafe { Unique::new(0 as *mut K) }; } } @@ -309,9 +313,9 @@ impl Node { let (vals_offset, edges_offset) = calculate_offsets_generic::(capacity, false); Node { - keys: Unique(buffer as *mut K), - vals: Unique(buffer.offset(vals_offset as isize) as *mut V), - edges: Unique(buffer.offset(edges_offset as isize) as *mut Node), + keys: Unique::new(buffer as *mut K), + vals: Unique::new(buffer.offset(vals_offset as isize) as *mut V), + edges: Some(Unique::new(buffer.offset(edges_offset as isize) as *mut Node)), _len: 0, _capacity: capacity, } @@ -327,9 +331,9 @@ impl Node { let (vals_offset, _) = calculate_offsets_generic::(capacity, true); Node { - keys: Unique(buffer as *mut K), - vals: Unique(unsafe { buffer.offset(vals_offset as isize) as *mut V }), - edges: Unique(ptr::null_mut()), + keys: unsafe { Unique::new(buffer as *mut K) }, + vals: unsafe { Unique::new(buffer.offset(vals_offset as isize) as *mut V) }, + edges: None, _len: 0, _capacity: capacity, } @@ -338,18 +342,18 @@ impl Node { unsafe fn destroy(&mut self) { let (alignment, size) = calculate_allocation_generic::(self.capacity(), self.is_leaf()); - heap::deallocate(self.keys.ptr as *mut u8, size, alignment); + heap::deallocate(*self.keys as *mut u8, size, alignment); } #[inline] pub fn as_slices<'a>(&'a self) -> (&'a [K], &'a [V]) { unsafe {( mem::transmute(raw::Slice { - data: self.keys.ptr, + data: *self.keys as *const K, len: self.len() }), mem::transmute(raw::Slice { - data: self.vals.ptr, + data: *self.vals as *const V, len: self.len() }) )} @@ -368,8 +372,12 @@ impl Node { &[] } else { unsafe { + let data = match self.edges { + None => heap::EMPTY as *const Node, + Some(ref p) => **p as *const Node, + }; mem::transmute(raw::Slice { - data: self.edges.ptr, + data: data, len: self.len() + 1 }) } @@ -525,7 +533,8 @@ impl Clone for Node { #[derive(Copy)] pub struct Handle { node: NodeRef, - index: usize + index: usize, + marker: PhantomData<(Type, NodeType)>, } pub mod handle { @@ -549,8 +558,8 @@ impl Node { // For the B configured as of this writing (B = 6), binary search was *significantly* // worse for usizes. match node.as_slices_internal().search_linear(key) { - (index, true) => Found(Handle { node: node, index: index }), - (index, false) => GoDown(Handle { node: node, index: index }), + (index, true) => Found(Handle { node: node, index: index, marker: PhantomData }), + (index, false) => GoDown(Handle { node: node, index: index, marker: PhantomData }), } } } @@ -587,7 +596,7 @@ impl Node { /// If the node has any children pub fn is_leaf(&self) -> bool { - self.edges.ptr.is_null() + self.edges.is_none() } /// if the node has too few elements @@ -619,7 +628,8 @@ impl Handle where pub fn as_raw(&mut self) -> Handle<*mut Node, Type, NodeType> { Handle { node: &mut *self.node as *mut _, - index: self.index + index: self.index, + marker: PhantomData, } } } @@ -631,7 +641,8 @@ impl Handle<*mut Node, Type, NodeType> { pub unsafe fn from_raw<'a>(&'a self) -> Handle<&'a Node, Type, NodeType> { Handle { node: &*self.node, - index: self.index + index: self.index, + marker: PhantomData, } } @@ -641,7 +652,8 @@ impl Handle<*mut Node, Type, NodeType> { pub unsafe fn from_raw_mut<'a>(&'a mut self) -> Handle<&'a mut Node, Type, NodeType> { Handle { node: &mut *self.node, - index: self.index + index: self.index, + marker: PhantomData, } } } @@ -689,12 +701,14 @@ impl>, Type> Handle Handle where unsafe fn left_kv<'a>(&'a mut self) -> Handle<&'a mut Node, handle::KV, NodeType> { Handle { node: &mut *self.node, - index: self.index - 1 + index: self.index - 1, + marker: PhantomData, } } @@ -837,7 +852,8 @@ impl Handle where unsafe fn right_kv<'a>(&'a mut self) -> Handle<&'a mut Node, handle::KV, NodeType> { Handle { node: &mut *self.node, - index: self.index + index: self.index, + marker: PhantomData, } } } @@ -877,7 +893,8 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<&'a mut Node, handle::KV, NodeType pub fn into_left_edge(self) -> Handle<&'a mut Node, handle::Edge, NodeType> { Handle { node: &mut *self.node, - index: self.index + index: self.index, + marker: PhantomData, } } } @@ -927,7 +944,8 @@ impl Handle where pub fn left_edge<'a>(&'a mut self) -> Handle<&'a mut Node, handle::Edge, NodeType> { Handle { node: &mut *self.node, - index: self.index + index: self.index, + marker: PhantomData, } } @@ -936,7 +954,8 @@ impl Handle where pub fn right_edge<'a>(&'a mut self) -> Handle<&'a mut Node, handle::Edge, NodeType> { Handle { node: &mut *self.node, - index: self.index + 1 + index: self.index + 1, + marker: PhantomData, } } } @@ -1045,7 +1064,8 @@ impl Node { debug_assert!(index < self.len(), "kv_handle index out of bounds"); Handle { node: self, - index: index + index: index, + marker: PhantomData, } } @@ -1065,7 +1085,7 @@ impl Node { vals: RawItems::from_slice(self.vals()), edges: RawItems::from_slice(self.edges()), - ptr: self.keys.ptr as *mut u8, + ptr: *self.keys as *mut u8, capacity: self.capacity(), is_leaf: self.is_leaf() }, diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index 140c9edb5a3..0c957426060 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -14,6 +14,7 @@ //! representation to hold C-like enum variants. use core::prelude::*; +use core::marker; use core::fmt; use core::num::Int; use core::iter::{FromIterator, IntoIterator}; @@ -26,7 +27,8 @@ use core::ops::{Sub, BitOr, BitAnd, BitXor}; pub struct EnumSet { // We must maintain the invariant that no bits are set // for which no variant exists - bits: usize + bits: usize, + marker: marker::PhantomData, } impl Copy for EnumSet {} @@ -86,7 +88,7 @@ impl EnumSet { #[unstable(feature = "collections", reason = "matches collection reform specification, waiting for dust to settle")] pub fn new() -> EnumSet { - EnumSet {bits: 0} + EnumSet {bits: 0, marker: marker::PhantomData} } /// Returns the number of elements in the given `EnumSet`. @@ -130,12 +132,14 @@ impl EnumSet { /// Returns the union of both `EnumSets`. pub fn union(&self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits | e.bits} + EnumSet {bits: self.bits | e.bits, + marker: marker::PhantomData} } /// Returns the intersection of both `EnumSets`. pub fn intersection(&self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits & e.bits} + EnumSet {bits: self.bits & e.bits, + marker: marker::PhantomData} } /// Adds an enum to the `EnumSet`, and returns `true` if it wasn't there before @@ -175,7 +179,7 @@ impl Sub for EnumSet { type Output = EnumSet; fn sub(self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits & !e.bits} + EnumSet {bits: self.bits & !e.bits, marker: marker::PhantomData} } } @@ -183,7 +187,7 @@ impl BitOr for EnumSet { type Output = EnumSet; fn bitor(self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits | e.bits} + EnumSet {bits: self.bits | e.bits, marker: marker::PhantomData} } } @@ -191,7 +195,7 @@ impl BitAnd for EnumSet { type Output = EnumSet; fn bitand(self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits & e.bits} + EnumSet {bits: self.bits & e.bits, marker: marker::PhantomData} } } @@ -199,7 +203,7 @@ impl BitXor for EnumSet { type Output = EnumSet; fn bitxor(self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits ^ e.bits} + EnumSet {bits: self.bits ^ e.bits, marker: marker::PhantomData} } } @@ -207,6 +211,7 @@ impl BitXor for EnumSet { pub struct Iter { index: usize, bits: usize, + marker: marker::PhantomData, } // FIXME(#19839) Remove in favor of `#[derive(Clone)]` @@ -215,13 +220,14 @@ impl Clone for Iter { Iter { index: self.index, bits: self.bits, + marker: marker::PhantomData, } } } impl Iter { fn new(bits: usize) -> Iter { - Iter { index: 0, bits: bits } + Iter { index: 0, bits: bits, marker: marker::PhantomData } } } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 1adcb77e0b6..1cc2a5235ab 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -57,13 +57,13 @@ use core::fmt; use core::hash::{self, Hash}; use core::intrinsics::assume; use core::iter::{repeat, FromIterator, IntoIterator}; -use core::marker::{self, ContravariantLifetime, InvariantType}; +use core::marker::PhantomData; use core::mem; -use core::nonzero::NonZero; use core::num::{Int, UnsignedInt}; use core::ops::{Index, IndexMut, Deref, Add}; use core::ops; use core::ptr; +use core::ptr::Unique; use core::raw::Slice as RawSlice; use core::slice; use core::usize; @@ -139,10 +139,9 @@ use borrow::{Cow, IntoCow}; #[unsafe_no_drop_flag] #[stable(feature = "rust1", since = "1.0.0")] pub struct Vec { - ptr: NonZero<*mut T>, + ptr: Unique, len: usize, cap: usize, - _own: marker::PhantomData, } unsafe impl Send for Vec { } @@ -251,10 +250,9 @@ impl Vec { pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Vec { Vec { - ptr: NonZero::new(ptr), + ptr: Unique::new(ptr), len: length, cap: capacity, - _own: marker::PhantomData, } } @@ -375,7 +373,7 @@ impl Vec { self.len * mem::size_of::(), mem::min_align_of::()) as *mut T; if ptr.is_null() { ::alloc::oom() } - self.ptr = NonZero::new(ptr); + self.ptr = Unique::new(ptr); } self.cap = self.len; } @@ -657,7 +655,7 @@ impl Vec { unsafe { let ptr = alloc_or_realloc(*self.ptr, old_size, size); if ptr.is_null() { ::alloc::oom() } - self.ptr = NonZero::new(ptr); + self.ptr = Unique::new(ptr); } self.cap = max(self.cap, 2) * 2; } @@ -758,7 +756,7 @@ impl Vec { Drain { ptr: begin, end: end, - marker: ContravariantLifetime, + marker: PhantomData, } } } @@ -873,6 +871,8 @@ impl Vec { end_t: unsafe { start.offset(offset) }, start_u: start as *mut U, end_u: start as *mut U, + + _marker: PhantomData, }; // start_t // start_u @@ -969,8 +969,7 @@ impl Vec { let mut pv = PartialVecZeroSized:: { num_t: vec.len(), num_u: 0, - marker_t: InvariantType, - marker_u: InvariantType, + marker: PhantomData, }; unsafe { mem::forget(vec); } @@ -1228,7 +1227,7 @@ impl Vec { unsafe { let ptr = alloc_or_realloc(*self.ptr, self.cap * mem::size_of::(), size); if ptr.is_null() { ::alloc::oom() } - self.ptr = NonZero::new(ptr); + self.ptr = Unique::new(ptr); } self.cap = capacity; } @@ -1795,10 +1794,10 @@ impl Drop for IntoIter { #[unsafe_no_drop_flag] #[unstable(feature = "collections", reason = "recently added as part of collections reform 2")] -pub struct Drain<'a, T> { +pub struct Drain<'a, T:'a> { ptr: *const T, end: *const T, - marker: ContravariantLifetime<'a>, + marker: PhantomData<&'a T>, } #[stable(feature = "rust1", since = "1.0.0")] @@ -1883,9 +1882,9 @@ impl<'a, T> Drop for Drain<'a, T> { /// Wrapper type providing a `&Vec` reference via `Deref`. #[unstable(feature = "collections")] -pub struct DerefVec<'a, T> { +pub struct DerefVec<'a, T:'a> { x: Vec, - l: ContravariantLifetime<'a> + l: PhantomData<&'a T>, } #[unstable(feature = "collections")] @@ -1913,7 +1912,7 @@ pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> { unsafe { DerefVec { x: Vec::from_raw_parts(x.as_ptr() as *mut T, x.len(), x.len()), - l: ContravariantLifetime::<'a> + l: PhantomData, } } } @@ -1937,6 +1936,8 @@ struct PartialVecNonZeroSized { end_u: *mut U, start_t: *mut T, end_t: *mut T, + + _marker: PhantomData, } /// An owned, partially type-converted vector of zero-sized elements. @@ -1946,8 +1947,7 @@ struct PartialVecNonZeroSized { struct PartialVecZeroSized { num_t: usize, num_u: usize, - marker_t: InvariantType, - marker_u: InvariantType, + marker: PhantomData<::core::cell::Cell<(T,U)>>, } #[unsafe_destructor] diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 712695841a2..3ba22a41ff7 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -28,7 +28,7 @@ use core::marker; use core::mem; use core::num::{Int, UnsignedInt}; use core::ops::{Index, IndexMut}; -use core::ptr; +use core::ptr::{self, Unique}; use core::raw::Slice as RawSlice; use core::hash::{Hash, Hasher}; @@ -57,7 +57,7 @@ pub struct VecDeque { tail: usize, head: usize, cap: usize, - ptr: *mut T + ptr: Unique, } #[stable(feature = "rust1", since = "1.0.0")] @@ -80,7 +80,7 @@ impl Drop for VecDeque { self.clear(); unsafe { if mem::size_of::() != 0 { - heap::deallocate(self.ptr as *mut u8, + heap::deallocate(*self.ptr as *mut u8, self.cap * mem::size_of::(), mem::min_align_of::()) } @@ -98,13 +98,13 @@ impl VecDeque { /// Turn ptr into a slice #[inline] unsafe fn buffer_as_slice(&self) -> &[T] { - mem::transmute(RawSlice { data: self.ptr, len: self.cap }) + mem::transmute(RawSlice { data: *self.ptr as *const T, len: self.cap }) } /// Turn ptr into a mut slice #[inline] unsafe fn buffer_as_mut_slice(&mut self) -> &mut [T] { - mem::transmute(RawSlice { data: self.ptr, len: self.cap }) + mem::transmute(RawSlice { data: *self.ptr as *const T, len: self.cap }) } /// Moves an element out of the buffer @@ -171,21 +171,21 @@ impl VecDeque { let size = cap.checked_mul(mem::size_of::()) .expect("capacity overflow"); - let ptr = if mem::size_of::() != 0 { - unsafe { + let ptr = unsafe { + if mem::size_of::() != 0 { let ptr = heap::allocate(size, mem::min_align_of::()) as *mut T;; if ptr.is_null() { ::alloc::oom() } - ptr + Unique::new(ptr) + } else { + Unique::new(heap::EMPTY as *mut T) } - } else { - heap::EMPTY as *mut T }; VecDeque { tail: 0, head: 0, cap: cap, - ptr: ptr + ptr: ptr, } } @@ -341,11 +341,12 @@ impl VecDeque { let new = count.checked_mul(mem::size_of::()) .expect("capacity overflow"); unsafe { - self.ptr = heap::reallocate(self.ptr as *mut u8, - old, - new, - mem::min_align_of::()) as *mut T; - if self.ptr.is_null() { ::alloc::oom() } + let ptr = heap::reallocate(*self.ptr as *mut u8, + old, + new, + mem::min_align_of::()) as *mut T; + if ptr.is_null() { ::alloc::oom() } + self.ptr = Unique::new(ptr); } } @@ -459,11 +460,12 @@ impl VecDeque { let old = self.cap * mem::size_of::(); let new_size = target_cap * mem::size_of::(); unsafe { - self.ptr = heap::reallocate(self.ptr as *mut u8, - old, - new_size, - mem::min_align_of::()) as *mut T; - if self.ptr.is_null() { ::alloc::oom() } + let ptr = heap::reallocate(*self.ptr as *mut u8, + old, + new_size, + mem::min_align_of::()) as *mut T; + if ptr.is_null() { ::alloc::oom() } + self.ptr = Unique::new(ptr); } } self.cap = target_cap; @@ -545,8 +547,8 @@ impl VecDeque { tail: self.tail, head: self.head, cap: self.cap, - ptr: self.ptr, - marker: marker::ContravariantLifetime, + ptr: *self.ptr, + marker: marker::PhantomData, } } @@ -1342,7 +1344,7 @@ impl VecDeque { // `at` lies in the first half. let amount_in_first = first_len - at; - ptr::copy_nonoverlapping_memory(other.ptr, + ptr::copy_nonoverlapping_memory(*other.ptr, first_half.as_ptr().offset(at as isize), amount_in_first); @@ -1355,7 +1357,7 @@ impl VecDeque { // in the first half. let offset = at - first_len; let amount_in_second = second_len - offset; - ptr::copy_nonoverlapping_memory(other.ptr, + ptr::copy_nonoverlapping_memory(*other.ptr, second_half.as_ptr().offset(offset as isize), amount_in_second); } @@ -1524,7 +1526,7 @@ pub struct IterMut<'a, T:'a> { tail: usize, head: usize, cap: usize, - marker: marker::ContravariantLifetime<'a>, + marker: marker::PhantomData<&'a mut T>, } #[stable(feature = "rust1", since = "1.0.0")] @@ -2004,9 +2006,9 @@ mod tests { #[derive(Clone, PartialEq, Debug)] enum Taggypar { - Onepar(i32), - Twopar(i32, i32), - Threepar(i32, i32, i32), + Onepar(T), + Twopar(T, T), + Threepar(T, T, T), } #[derive(Clone, PartialEq, Debug)] diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 9f0489a4f96..54589a31423 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -876,7 +876,7 @@ pub struct IntoIter { } #[unstable(feature = "collections")] -pub struct Drain<'a, V> { +pub struct Drain<'a, V:'a> { iter: FilterMap< Enumerate>>, fn((usize, Option)) -> Option<(usize, V)>> diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs index 05d864accc1..6afe5b2257d 100644 --- a/src/libcore/atomic.rs +++ b/src/libcore/atomic.rs @@ -76,6 +76,7 @@ use marker::Sync; use intrinsics; use cell::UnsafeCell; +use marker::PhantomData; /// A boolean type which can be safely shared between threads. #[stable(feature = "rust1", since = "1.0.0")] @@ -105,6 +106,7 @@ unsafe impl Sync for AtomicUsize {} #[stable(feature = "rust1", since = "1.0.0")] pub struct AtomicPtr { p: UnsafeCell, + _marker: PhantomData<*mut T>, } unsafe impl Sync for AtomicPtr {} @@ -791,7 +793,8 @@ impl AtomicPtr { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn new(p: *mut T) -> AtomicPtr { - AtomicPtr { p: UnsafeCell::new(p as usize) } + AtomicPtr { p: UnsafeCell::new(p as usize), + _marker: PhantomData } } /// Loads a value from the pointer. diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 67c8c9fec09..a2c1bbc0331 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -16,7 +16,7 @@ use any; use cell::{Cell, RefCell, Ref, RefMut, BorrowState}; use char::CharExt; use iter::{Iterator, IteratorExt}; -use marker::{Copy, Sized}; +use marker::{Copy, PhantomData, Sized}; use mem; use option::Option; use option::Option::{Some, None}; @@ -914,6 +914,11 @@ impl Debug for () { f.pad("()") } } +impl Debug for PhantomData { + fn fmt(&self, f: &mut Formatter) -> Result { + f.pad("PhantomData") + } +} #[stable(feature = "rust1", since = "1.0.0")] impl Debug for Cell { diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 194c0dc4f28..8fb10b5b2dc 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -62,6 +62,7 @@ use clone::Clone; use cmp; use cmp::Ord; use default::Default; +use marker; use mem; use num::{ToPrimitive, Int}; use ops::{Add, Deref, FnMut}; @@ -947,7 +948,7 @@ pub trait IteratorExt: Iterator + Sized { FromB: Default + Extend, Self: Iterator, { - struct SizeHint(usize, Option); + struct SizeHint(usize, Option, marker::PhantomData); impl Iterator for SizeHint { type Item = A; @@ -961,8 +962,8 @@ pub trait IteratorExt: Iterator + Sized { let mut ts: FromA = Default::default(); let mut us: FromB = Default::default(); - ts.extend(SizeHint(lo, hi)); - us.extend(SizeHint(lo, hi)); + ts.extend(SizeHint(lo, hi, marker::PhantomData)); + us.extend(SizeHint(lo, hi, marker::PhantomData)); for (t, u) in self { ts.extend(Some(t).into_iter()); @@ -2064,8 +2065,8 @@ pub struct Scan { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Scan where - F: FnMut(&mut St, I::Item) -> Option, +impl, St, F> Iterator for Scan where + F: FnMut(&mut St, A) -> Option, { type Item = B; diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 56e1c5dedc1..dc792a3f47f 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -26,6 +26,10 @@ #![stable(feature = "rust1", since = "1.0.0")] use clone::Clone; +use cmp; +use option::Option; +use hash::Hash; +use hash::Hasher; /// Types able to be transferred across thread boundaries. #[unstable(feature = "core", @@ -37,12 +41,11 @@ pub unsafe trait Send: 'static { // empty. } /// Types able to be transferred across thread boundaries. -#[unstable(feature = "core", - reason = "will be overhauled with new lifetime rules; see RFC 458")] +#[stable(feature = "rust1", since = "1.0.0")] #[lang="send"] #[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"] #[cfg(not(stage0))] -pub unsafe trait Send { +pub unsafe trait Send : MarkerTrait { // empty. } @@ -50,7 +53,7 @@ pub unsafe trait Send { #[stable(feature = "rust1", since = "1.0.0")] #[lang="sized"] #[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"] -pub trait Sized { +pub trait Sized : MarkerTrait { // Empty. } @@ -155,7 +158,7 @@ pub trait Sized { /// change: that second example would fail to compile if we made `Foo` non-`Copy`. #[stable(feature = "rust1", since = "1.0.0")] #[lang="copy"] -pub trait Copy { +pub trait Copy : MarkerTrait { // Empty. } @@ -204,220 +207,13 @@ pub trait Copy { /// around the value(s) which can be mutated when behind a `&` /// reference; not doing this is undefined behaviour (for example, /// `transmute`-ing from `&T` to `&mut T` is illegal). -#[unstable(feature = "core", - reason = "will be overhauled with new lifetime rules; see RFC 458")] +#[stable(feature = "rust1", since = "1.0.0")] #[lang="sync"] #[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"] -pub unsafe trait Sync { +pub unsafe trait Sync : MarkerTrait { // Empty } -/// A marker type that indicates to the compiler that the instances -/// of the type itself owns instances of the type parameter `T`. -/// -/// This is used to indicate that one or more instances of the type -/// `T` could be dropped when instances of the type itself is dropped, -/// though that may not be apparent from the other structure of the -/// type itself. For example, the type may hold a `*mut T`, which the -/// compiler does not automatically treat as owned. -#[unstable(feature = "core", - reason = "Newly added to deal with scoping and destructor changes")] -#[lang="phantom_data"] -#[derive(PartialEq, Eq, PartialOrd, Ord)] -pub struct PhantomData; - -impl Copy for PhantomData {} -impl Clone for PhantomData { - fn clone(&self) -> PhantomData { *self } -} - -/// A marker type whose type parameter `T` is considered to be -/// covariant with respect to the type itself. This is (typically) -/// used to indicate that an instance of the type `T` is being stored -/// into memory and read from, even though that may not be apparent. -/// -/// For more information about variance, refer to this Wikipedia -/// article . -/// -/// *Note:* It is very unusual to have to add a covariant constraint. -/// If you are not sure, you probably want to use `InvariantType`. -/// -/// # Example -/// -/// Given a struct `S` that includes a type parameter `T` -/// but does not actually *reference* that type parameter: -/// -/// ```ignore -/// use std::mem; -/// -/// struct S { x: *() } -/// fn get(s: &S) -> T { -/// unsafe { -/// let x: *T = mem::transmute(s.x); -/// *x -/// } -/// } -/// ``` -/// -/// The type system would currently infer that the value of -/// the type parameter `T` is irrelevant, and hence a `S` is -/// a subtype of `S>` (or, for that matter, `S` for -/// any `U`). But this is incorrect because `get()` converts the -/// `*()` into a `*T` and reads from it. Therefore, we should include the -/// a marker field `CovariantType` to inform the type checker that -/// `S` is a subtype of `S` if `T` is a subtype of `U` -/// (for example, `S<&'static int>` is a subtype of `S<&'a int>` -/// for some lifetime `'a`, but not the other way around). -#[unstable(feature = "core", - reason = "likely to change with new variance strategy")] -#[lang="covariant_type"] -#[derive(PartialEq, Eq, PartialOrd, Ord)] -pub struct CovariantType; - -impl Copy for CovariantType {} -impl Clone for CovariantType { - fn clone(&self) -> CovariantType { *self } -} - -/// A marker type whose type parameter `T` is considered to be -/// contravariant with respect to the type itself. This is (typically) -/// used to indicate that an instance of the type `T` will be consumed -/// (but not read from), even though that may not be apparent. -/// -/// For more information about variance, refer to this Wikipedia -/// article . -/// -/// *Note:* It is very unusual to have to add a contravariant constraint. -/// If you are not sure, you probably want to use `InvariantType`. -/// -/// # Example -/// -/// Given a struct `S` that includes a type parameter `T` -/// but does not actually *reference* that type parameter: -/// -/// ``` -/// use std::mem; -/// -/// struct S { x: *const () } -/// fn get(s: &S, v: T) { -/// unsafe { -/// let x: fn(T) = mem::transmute(s.x); -/// x(v) -/// } -/// } -/// ``` -/// -/// The type system would currently infer that the value of -/// the type parameter `T` is irrelevant, and hence a `S` is -/// a subtype of `S>` (or, for that matter, `S` for -/// any `U`). But this is incorrect because `get()` converts the -/// `*()` into a `fn(T)` and then passes a value of type `T` to it. -/// -/// Supplying a `ContravariantType` marker would correct the -/// problem, because it would mark `S` so that `S` is only a -/// subtype of `S` if `U` is a subtype of `T`; given that the -/// function requires arguments of type `T`, it must also accept -/// arguments of type `U`, hence such a conversion is safe. -#[unstable(feature = "core", - reason = "likely to change with new variance strategy")] -#[lang="contravariant_type"] -#[derive(PartialEq, Eq, PartialOrd, Ord)] -pub struct ContravariantType; - -impl Copy for ContravariantType {} -impl Clone for ContravariantType { - fn clone(&self) -> ContravariantType { *self } -} - -/// A marker type whose type parameter `T` is considered to be -/// invariant with respect to the type itself. This is (typically) -/// used to indicate that instances of the type `T` may be read or -/// written, even though that may not be apparent. -/// -/// For more information about variance, refer to this Wikipedia -/// article . -/// -/// # Example -/// -/// The Cell type is an example of an `InvariantType` which uses unsafe -/// code to achieve "interior" mutability: -/// -/// ``` -/// struct Cell { value: T } -/// ``` -/// -/// The type system would infer that `value` is only read here -/// and never written, but in fact `Cell` uses unsafe code to achieve -/// interior mutability. In order to get correct behavior, the -/// `InvariantType` marker must be applied. -#[unstable(feature = "core", - reason = "likely to change with new variance strategy")] -#[lang="invariant_type"] -#[derive(PartialEq, Eq, PartialOrd, Ord)] -pub struct InvariantType; - -#[unstable(feature = "core", - reason = "likely to change with new variance strategy")] -impl Copy for InvariantType {} -#[unstable(feature = "core", - reason = "likely to change with new variance strategy")] -impl Clone for InvariantType { - fn clone(&self) -> InvariantType { *self } -} - -/// As `CovariantType`, but for lifetime parameters. Using -/// `CovariantLifetime<'a>` indicates that it is ok to substitute -/// a *longer* lifetime for `'a` than the one you originally -/// started with (e.g., you could convert any lifetime `'foo` to -/// `'static`). You almost certainly want `ContravariantLifetime` -/// instead, or possibly `InvariantLifetime`. The only case where -/// it would be appropriate is that you have a (type-casted, and -/// hence hidden from the type system) function pointer with a -/// signature like `fn(&'a T)` (and no other uses of `'a`). In -/// this case, it is ok to substitute a larger lifetime for `'a` -/// (e.g., `fn(&'static T)`), because the function is only -/// becoming more selective in terms of what it accepts as -/// argument. -/// -/// For more information about variance, refer to this Wikipedia -/// article . -#[unstable(feature = "core", - reason = "likely to change with new variance strategy")] -#[lang="covariant_lifetime"] -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub struct CovariantLifetime<'a>; - -/// As `ContravariantType`, but for lifetime parameters. Using -/// `ContravariantLifetime<'a>` indicates that it is ok to -/// substitute a *shorter* lifetime for `'a` than the one you -/// originally started with (e.g., you could convert `'static` to -/// any lifetime `'foo`). This is appropriate for cases where you -/// have an unsafe pointer that is actually a pointer into some -/// memory with lifetime `'a`, and thus you want to limit the -/// lifetime of your data structure to `'a`. An example of where -/// this is used is the iterator for vectors. -/// -/// For more information about variance, refer to this Wikipedia -/// article . -#[unstable(feature = "core", - reason = "likely to change with new variance strategy")] -#[lang="contravariant_lifetime"] -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub struct ContravariantLifetime<'a>; - -/// As `InvariantType`, but for lifetime parameters. Using -/// `InvariantLifetime<'a>` indicates that it is not ok to -/// substitute any other lifetime for `'a` besides its original -/// value. This is appropriate for cases where you have an unsafe -/// pointer that is actually a pointer into memory with lifetime `'a`, -/// and this pointer is itself stored in an inherently mutable -/// location (such as a `Cell`). -#[unstable(feature = "core", - reason = "likely to change with new variance strategy")] -#[lang="invariant_lifetime"] -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub struct InvariantLifetime<'a>; - /// A type which is considered "not POD", meaning that it is not /// implicitly copyable. This is typically embedded in other types to /// ensure that they are never copied, even if they lack a destructor. @@ -435,6 +231,149 @@ pub struct NoCopy; #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Managed; +macro_rules! impls{ + ($t: ident) => ( + impl Hash for $t { + #[inline] + fn hash(&self, _: &mut S) { + } + } + + impl cmp::PartialEq for $t { + fn eq(&self, _other: &$t) -> bool { + true + } + } + + impl cmp::Eq for $t { + } + + impl cmp::PartialOrd for $t { + fn partial_cmp(&self, _other: &$t) -> Option { + Option::Some(cmp::Ordering::Equal) + } + } + + impl cmp::Ord for $t { + fn cmp(&self, _other: &$t) -> cmp::Ordering { + cmp::Ordering::Equal + } + } + + impl Copy for $t { } + + impl Clone for $t { + fn clone(&self) -> $t { + $t + } + } + ) +} + +/// `MarkerTrait` is intended to be used as the supertrait for traits +/// that don't have any methods but instead serve just to designate +/// categories of types. An example would be the `Send` trait, which +/// indicates types that are sendable: `Send` does not itself offer +/// any methods, but instead is used to gate access to data. +/// +/// FIXME. Better documentation needed here! +pub trait MarkerTrait : PhantomFn { } +impl MarkerTrait for T { } + +/// `PhantomFn` is a marker trait for use with traits that contain +/// type or lifetime parameters that do not appear in any of their +/// methods. In that case, you can either remove those parameters, or +/// add a `PhantomFn` supertrait that reflects the signature of +/// methods that compiler should "pretend" exists. This most commonly +/// occurs for traits with no methods: in that particular case, you +/// can extend `MarkerTrait`, which is equivalent to +/// `PhantomFn`. +/// +/// # Example +/// +/// As an example, consider a trait with no methods like `Even`, meant +/// to represent types that are "even": +/// +/// ```rust +/// trait Even { } +/// ``` +/// +/// In this case, because the implicit parameter `Self` is unused, the +/// compiler will issue an error. The only purpose of this trait is to +/// categorize types (and hence instances of those types) as "even" or +/// not, so if we *were* going to have a method, it might look like: +/// +/// ```rust +/// trait Even { +/// fn is_even(self) -> bool { true } +/// } +/// ``` +/// +/// Therefore, we can model a method like this as follows: +/// +/// ```rust +/// use std::marker::PhantomFn +/// trait Even : PhantomFn { } +/// ``` +/// +/// Another equivalent, but clearer, option would be to use +/// `MarkerTrait`: +/// +/// ```rust +/// use std::marker::MarkerTrait; +/// trait Even : MarkerTrait { } +/// ``` +/// +/// # Parameters +/// +/// - `A` represents the type of the method's argument. You can use a +/// tuple to represent "multiple" arguments. Any types appearing here +/// will be considered "contravariant". +/// - `R`, if supplied, represents the method's return type. This defaults +/// to `()` as it is rarely needed. +/// +/// # Additional reading +/// +/// More details and background can be found in [RFC 738][738]. +/// +/// [738]: https://github.com/rust-lang/rfcs/blob/master/text/0738-variance.md +#[lang="phantom_fn"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait PhantomFn { } + +#[cfg(stage0)] // built into the trait matching system after stage0 +impl PhantomFn for U { } + +/// Specific to stage0. You should not be seeing these docs! +#[cfg(stage0)] +#[lang="covariant_type"] // only relevant to stage0 +pub struct PhantomData; + +/// `PhantomData` is a way to tell the compiler about fake fields. +/// Phantom data is required whenever type parameters are not used. +/// The idea is that if the compiler encounters a `PhantomData` +/// instance, it will behave *as if* an instance of the type `T` were +/// present for the purpose of various automatic analyses. +/// +/// For example, embedding a `PhantomData` will inform the compiler +/// that one or more instances of the type `T` could be dropped when +/// instances of the type itself is dropped, though that may not be +/// apparent from the other structure of the type itself. This is +/// commonly necessary if the structure is using an unsafe pointer +/// like `*mut T` whose referent may be dropped when the type is +/// dropped, as a `*mut T` is otherwise not treated as owned. +/// +/// FIXME. Better documentation and examples of common patterns needed +/// here! For now, please see [RFC 738][738] for more information. +/// +/// [738]: https://github.com/rust-lang/rfcs/blob/master/text/0738-variance.md +#[cfg(not(stage0))] +#[lang="phantom_data"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct PhantomData; + +impls! { PhantomData } + #[cfg(not(stage0))] mod impls { use super::{Send, Sync, Sized}; @@ -442,3 +381,40 @@ mod impls { unsafe impl<'a, T: Sync + ?Sized> Send for &'a T {} unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {} } + +/// Old-style marker trait. Deprecated. +#[unstable(feature = "core", reason = "deprecated")] +#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<&'a ()>`")] +#[lang="contravariant_lifetime"] +pub struct ContravariantLifetime<'a>; + +/// Old-style marker trait. Deprecated. +#[unstable(feature = "core", reason = "deprecated")] +#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData`")] +#[lang="covariant_lifetime"] +pub struct CovariantLifetime<'a>; + +/// Old-style marker trait. Deprecated. +#[unstable(feature = "core", reason = "deprecated")] +#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData>`")] +#[lang="invariant_lifetime"] +pub struct InvariantLifetime<'a>; + +/// Old-style marker trait. Deprecated. +#[unstable(feature = "core", reason = "deprecated")] +#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData`")] +#[lang="contravariant_type"] +pub struct ContravariantType; + +/// Old-style marker trait. Deprecated. +#[unstable(feature = "core", reason = "deprecated")] +#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData`")] +#[lang="covariant_type"] +#[cfg(not(stage0))] +pub struct CovariantType; + +/// Old-style marker trait. Deprecated. +#[unstable(feature = "core", reason = "deprecated")] +#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData>`")] +#[lang="invariant_type"] +pub struct InvariantType; diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index 5644f763069..230587b726f 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -10,15 +10,14 @@ //! Exposes the NonZero lang item which provides optimization hints. +use marker::{Sized, MarkerTrait}; use ops::Deref; -use ptr::Unique; /// Unsafe trait to indicate what types are usable with the NonZero struct -pub unsafe trait Zeroable {} +pub unsafe trait Zeroable : MarkerTrait {} -unsafe impl Zeroable for *const T {} -unsafe impl Zeroable for *mut T {} -unsafe impl Zeroable for Unique { } +unsafe impl Zeroable for *const T {} +unsafe impl Zeroable for *mut T {} unsafe impl Zeroable for isize {} unsafe impl Zeroable for usize {} unsafe impl Zeroable for i8 {} diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 2779e67c743..16b84dcf18e 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -91,8 +91,10 @@ use mem; use clone::Clone; use intrinsics; +use ops::Deref; use option::Option::{self, Some, None}; -use marker::{self, Send, Sized, Sync}; +use marker::{PhantomData, Send, Sized, Sync}; +use nonzero::NonZero; use cmp::{PartialEq, Eq, Ord, PartialOrd}; use cmp::Ordering::{self, Less, Equal, Greater}; @@ -517,15 +519,16 @@ impl PartialOrd for *mut T { /// A wrapper around a raw `*mut T` that indicates that the possessor /// of this wrapper owns the referent. This in turn implies that the -/// `Unique` is `Send`/`Sync` if `T` is `Send`/`Sync`, unlike a -/// raw `*mut T` (which conveys no particular ownership semantics). -/// Useful for building abstractions like `Vec` or `Box`, which +/// `Unique` is `Send`/`Sync` if `T` is `Send`/`Sync`, unlike a raw +/// `*mut T` (which conveys no particular ownership semantics). It +/// also implies that the referent of the pointer should not be +/// modified without a unique path to the `Unique` reference. Useful +/// for building abstractions like `Vec` or `Box`, which /// internally use raw pointers to manage the memory that they own. #[unstable(feature = "core", reason = "recently added to this module")] -pub struct Unique { - /// The wrapped `*mut T`. - pub ptr: *mut T, - _own: marker::PhantomData, +pub struct Unique { + pointer: NonZero<*const T>, + _marker: PhantomData, } /// `Unique` pointers are `Send` if `T` is `Send` because the data they @@ -542,25 +545,34 @@ unsafe impl Send for Unique { } #[unstable(feature = "core", reason = "recently added to this module")] unsafe impl Sync for Unique { } -impl Unique { - /// Returns a null Unique. +impl Unique { + /// Create a new `Unique`. #[unstable(feature = "core", reason = "recently added to this module")] - pub fn null() -> Unique { - Unique(null_mut()) + pub unsafe fn new(ptr: *mut T) -> Unique { + Unique { pointer: NonZero::new(ptr as *const T), _marker: PhantomData } } - /// Return an (unsafe) pointer into the memory owned by `self`. + /// Dereference the content. #[unstable(feature = "core", reason = "recently added to this module")] - pub unsafe fn offset(self, offset: isize) -> *mut T { - self.ptr.offset(offset) + pub unsafe fn get(&self) -> &T { + &**self.pointer + } + + /// Mutably dereference the content. + #[unstable(feature = "core", + reason = "recently added to this module")] + pub unsafe fn get_mut(&mut self) -> &mut T { + &mut ***self } } -/// Creates a `Unique` wrapped around `ptr`, taking ownership of the -/// data referenced by `ptr`. -#[allow(non_snake_case)] -pub fn Unique(ptr: *mut T) -> Unique { - Unique { ptr: ptr, _own: marker::PhantomData } +impl Deref for Unique { + type Target = *mut T; + + #[inline] + fn deref<'a>(&'a self) -> &'a *mut T { + unsafe { mem::transmute(&*self.pointer) } + } } diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index bbfe7e58ef4..a86da53b372 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -140,11 +140,11 @@ impl SliceExt for [T] { if mem::size_of::() == 0 { Iter {ptr: p, end: (p as usize + self.len()) as *const T, - marker: marker::ContravariantLifetime::<'a>} + _marker: marker::PhantomData} } else { Iter {ptr: p, end: p.offset(self.len() as isize), - marker: marker::ContravariantLifetime::<'a>} + _marker: marker::PhantomData} } } } @@ -279,11 +279,11 @@ impl SliceExt for [T] { if mem::size_of::() == 0 { IterMut {ptr: p, end: (p as usize + self.len()) as *mut T, - marker: marker::ContravariantLifetime::<'a>} + _marker: marker::PhantomData} } else { IterMut {ptr: p, end: p.offset(self.len() as isize), - marker: marker::ContravariantLifetime::<'a>} + _marker: marker::PhantomData} } } } @@ -733,7 +733,7 @@ macro_rules! make_slice { pub struct Iter<'a, T: 'a> { ptr: *const T, end: *const T, - marker: marker::ContravariantLifetime<'a> + _marker: marker::PhantomData<&'a T>, } #[unstable(feature = "core")] @@ -790,7 +790,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Clone for Iter<'a, T> { - fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, marker: self.marker } } + fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, _marker: self._marker } } } #[unstable(feature = "core", reason = "trait is experimental")] @@ -823,7 +823,7 @@ impl<'a, T> RandomAccessIterator for Iter<'a, T> { pub struct IterMut<'a, T: 'a> { ptr: *mut T, end: *mut T, - marker: marker::ContravariantLifetime<'a>, + _marker: marker::PhantomData<&'a mut T>, } diff --git a/src/libcoretest/mem.rs b/src/libcoretest/mem.rs index 421ce76caaf..5aeb330b78b 100644 --- a/src/libcoretest/mem.rs +++ b/src/libcoretest/mem.rs @@ -92,7 +92,7 @@ fn test_transmute_copy() { #[test] fn test_transmute() { - trait Foo {} + trait Foo { fn dummy(&self) { } } impl Foo for int {} let a = box 100 as Box; diff --git a/src/libcoretest/ptr.rs b/src/libcoretest/ptr.rs index 9c2e242c105..57456bfb1a7 100644 --- a/src/libcoretest/ptr.rs +++ b/src/libcoretest/ptr.rs @@ -171,8 +171,8 @@ fn test_set_memory() { #[test] fn test_unsized_unique() { let xs: &mut [_] = &mut [1, 2, 3]; - let ptr = Unique(xs as *mut [_]); - let ys = unsafe { &mut *ptr.ptr }; + let ptr = unsafe { Unique::new(xs as *mut [_]) }; + let ys = unsafe { &mut **ptr }; let zs: &mut [_] = &mut [1, 2, 3]; assert!(ys == zs); } diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index ff6400a11df..24660b3f396 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -45,13 +45,13 @@ pub struct Bytes { impl Deref for Bytes { type Target = [u8]; fn deref(&self) -> &[u8] { - unsafe { slice::from_raw_parts_mut(self.ptr.ptr, self.len) } + unsafe { slice::from_raw_parts(*self.ptr, self.len) } } } impl Drop for Bytes { fn drop(&mut self) { - unsafe { libc::free(self.ptr.ptr as *mut _); } + unsafe { libc::free(*self.ptr as *mut _); } } } @@ -84,7 +84,7 @@ fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option { &mut outsz, flags); if !res.is_null() { - let res = Unique(res as *mut u8); + let res = Unique::new(res as *mut u8); Some(Bytes { ptr: res, len: outsz as uint }) } else { None @@ -110,7 +110,7 @@ fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option { &mut outsz, flags); if !res.is_null() { - let res = Unique(res as *mut u8); + let res = Unique::new(res as *mut u8); Some(Bytes { ptr: res, len: outsz as uint }) } else { None diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs index d1d24cea871..5a85552dc38 100644 --- a/src/librand/distributions/mod.rs +++ b/src/librand/distributions/mod.rs @@ -21,6 +21,7 @@ use core::prelude::*; use core::num::{Float, Int}; +use core::marker::PhantomData; use {Rng, Rand}; @@ -56,7 +57,13 @@ pub trait IndependentSample: Sample { /// A wrapper for generating types that implement `Rand` via the /// `Sample` & `IndependentSample` traits. -pub struct RandSample; +pub struct RandSample { _marker: PhantomData } + +impl RandSample { + pub fn new() -> RandSample { + RandSample { _marker: PhantomData } + } +} impl Sample for RandSample { fn sample(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) } @@ -285,7 +292,7 @@ mod tests { #[test] fn test_rand_sample() { - let mut rand_sample = RandSample::; + let mut rand_sample = RandSample::::new(); assert_eq!(rand_sample.sample(&mut ::test::rng()), ConstRand(0)); assert_eq!(rand_sample.ind_sample(&mut ::test::rng()), ConstRand(0)); diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 915c70bbf8c..7588bf7c515 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -41,6 +41,7 @@ extern crate core; #[cfg(test)] #[macro_use] extern crate log; use core::prelude::*; +use core::marker::PhantomData; pub use isaac::{IsaacRng, Isaac64Rng}; pub use chacha::ChaChaRng; @@ -206,7 +207,7 @@ pub trait Rng : Sized { /// .collect::>()); /// ``` fn gen_iter<'a, T: Rand>(&'a mut self) -> Generator<'a, T, Self> { - Generator { rng: self } + Generator { rng: self, _marker: PhantomData } } /// Generate a random value in the range [`low`, `high`). @@ -317,6 +318,7 @@ pub trait Rng : Sized { /// This iterator is created via the `gen_iter` method on `Rng`. pub struct Generator<'a, T, R:'a> { rng: &'a mut R, + _marker: PhantomData } impl<'a, T: Rand, R: Rng> Iterator for Generator<'a, T, R> { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 147fc5ea7f9..e99d214742a 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -29,7 +29,6 @@ use middle::ty::{MethodOrigin, MethodParam, MethodTypeParam}; use middle::ty::{MethodStatic, MethodStaticClosure}; use util::ppaux::Repr; -use std::marker; use syntax::{ast, ast_util}; use syntax::ptr::P; use syntax::codemap::Span; @@ -128,16 +127,14 @@ pub enum MatchMode { MovingMatch, } -#[derive(PartialEq,Debug)] -enum TrackMatchMode { +#[derive(Copy, PartialEq, Debug)] +enum TrackMatchMode { Unknown, Definite(MatchMode), Conflicting, } -impl marker::Copy for TrackMatchMode {} - -impl TrackMatchMode { +impl TrackMatchMode { // Builds up the whole match mode for a pattern from its constituent // parts. The lattice looks like this: // @@ -931,7 +928,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { return true; } - fn arm_move_mode(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &ast::Arm) -> TrackMatchMode { + fn arm_move_mode(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &ast::Arm) -> TrackMatchMode { let mut mode = Unknown; for pat in &arm.pats { self.determine_pat_move_mode(discr_cmt.clone(), &**pat, &mut mode); @@ -966,7 +963,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { fn determine_pat_move_mode(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &ast::Pat, - mode: &mut TrackMatchMode) { + mode: &mut TrackMatchMode) { debug!("determine_pat_move_mode cmt_discr={} pat={}", cmt_discr.repr(self.tcx()), pat.repr(self.tcx())); return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| { diff --git a/src/librustc/middle/infer/bivariate.rs b/src/librustc/middle/infer/bivariate.rs new file mode 100644 index 00000000000..93c80fb754f --- /dev/null +++ b/src/librustc/middle/infer/bivariate.rs @@ -0,0 +1,145 @@ +// 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. + +//! Applies the "bivariance relationship" to two types and/or regions. +//! If (A,B) are bivariant then either A <: B or B <: A. It occurs +//! when type/lifetime parameters are unconstrained. Usually this is +//! an error, but we permit it in the specific case where a type +//! parameter is constrained in a where-clause via an associated type. +//! +//! There are several ways one could implement bivariance. You could +//! just do nothing at all, for example, or you could fully verify +//! that one of the two subtyping relationships hold. We choose to +//! thread a middle line: we relate types up to regions, but ignore +//! all region relationships. +//! +//! At one point, handling bivariance in this fashion was necessary +//! for inference, but I'm actually not sure if that is true anymore. +//! In particular, it might be enough to say (A,B) are bivariant for +//! all (A,B). + +use middle::ty::{BuiltinBounds}; +use middle::ty::{self, Ty}; +use middle::ty::TyVar; +use middle::infer::combine::*; +use middle::infer::{cres}; +use middle::infer::type_variable::{BiTo}; +use util::ppaux::{Repr}; + +use syntax::ast::{Unsafety}; + +pub struct Bivariate<'f, 'tcx: 'f> { + fields: CombineFields<'f, 'tcx> +} + +#[allow(non_snake_case)] +pub fn Bivariate<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Bivariate<'f, 'tcx> { + Bivariate { fields: cf } +} + +impl<'f, 'tcx> Combine<'tcx> for Bivariate<'f, 'tcx> { + fn tag(&self) -> String { "Bivariate".to_string() } + fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields } + + fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>) + -> cres<'tcx, Ty<'tcx>> + { + match v { + ty::Invariant => self.equate().tys(a, b), + ty::Covariant => self.tys(a, b), + ty::Contravariant => self.tys(a, b), + ty::Bivariant => self.tys(a, b), + } + } + + fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region) + -> cres<'tcx, ty::Region> + { + match v { + ty::Invariant => self.equate().regions(a, b), + ty::Covariant => self.regions(a, b), + ty::Contravariant => self.regions(a, b), + ty::Bivariant => self.regions(a, b), + } + } + + fn regions(&self, a: ty::Region, _: ty::Region) -> cres<'tcx, ty::Region> { + Ok(a) + } + + fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>> { + debug!("mts({} <: {})", + a.repr(self.fields.infcx.tcx), + b.repr(self.fields.infcx.tcx)); + + if a.mutbl != b.mutbl { return Err(ty::terr_mutability); } + let t = try!(self.tys(a.ty, b.ty)); + Ok(ty::mt { mutbl: a.mutbl, ty: t }) + } + + fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> { + if a != b { + Err(ty::terr_unsafety_mismatch(expected_found(self, a, b))) + } else { + Ok(a) + } + } + + fn builtin_bounds(&self, + a: BuiltinBounds, + b: BuiltinBounds) + -> cres<'tcx, BuiltinBounds> + { + if a != b { + Err(ty::terr_builtin_bounds(expected_found(self, a, b))) + } else { + Ok(a) + } + } + + fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> { + debug!("{}.tys({}, {})", self.tag(), + a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx)); + if a == b { return Ok(a); } + + let infcx = self.fields.infcx; + let a = infcx.type_variables.borrow().replace_if_possible(a); + let b = infcx.type_variables.borrow().replace_if_possible(b); + match (&a.sty, &b.sty) { + (&ty::ty_infer(TyVar(a_id)), &ty::ty_infer(TyVar(b_id))) => { + infcx.type_variables.borrow_mut().relate_vars(a_id, BiTo, b_id); + Ok(a) + } + + (&ty::ty_infer(TyVar(a_id)), _) => { + try!(self.fields.instantiate(b, BiTo, a_id)); + Ok(a) + } + + (_, &ty::ty_infer(TyVar(b_id))) => { + try!(self.fields.instantiate(a, BiTo, b_id)); + Ok(a) + } + + _ => { + super_tys(self, a, b) + } + } + } + + fn binders(&self, a: &ty::Binder, b: &ty::Binder) -> cres<'tcx, ty::Binder> + where T : Combineable<'tcx> + { + let a1 = ty::erase_late_bound_regions(self.tcx(), a); + let b1 = ty::erase_late_bound_regions(self.tcx(), b); + let c = try!(Combineable::combine(self, &a1, &b1)); + Ok(ty::Binder(c)) + } +} diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index 70b444d81d8..0eeafb767d8 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -32,6 +32,7 @@ // is also useful to track which value is the "expected" value in // terms of error reporting. +use super::bivariate::Bivariate; use super::equate::Equate; use super::glb::Glb; use super::lub::Lub; @@ -39,7 +40,7 @@ use super::sub::Sub; use super::unify::InferCtxtMethodsForSimplyUnifiableTypes; use super::{InferCtxt, cres}; use super::{MiscVariable, TypeTrace}; -use super::type_variable::{RelationDir, EqTo, SubtypeOf, SupertypeOf}; +use super::type_variable::{RelationDir, BiTo, EqTo, SubtypeOf, SupertypeOf}; use middle::subst; use middle::subst::{ErasedRegions, NonerasedRegions, Substs}; @@ -48,7 +49,7 @@ use middle::ty::{IntType, UintType}; use middle::ty::{BuiltinBounds}; use middle::ty::{self, Ty}; use middle::ty_fold; -use middle::ty_fold::{TypeFoldable}; +use middle::ty_fold::{TypeFolder, TypeFoldable}; use util::ppaux::Repr; use std::rc::Rc; @@ -58,41 +59,32 @@ use syntax::abi; use syntax::codemap::Span; pub trait Combine<'tcx> : Sized { - fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx>; fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.infcx().tcx } fn tag(&self) -> String; - fn a_is_expected(&self) -> bool; - fn trace(&self) -> TypeTrace<'tcx>; - fn equate<'a>(&'a self) -> Equate<'a, 'tcx>; - fn sub<'a>(&'a self) -> Sub<'a, 'tcx>; - fn lub<'a>(&'a self) -> Lub<'a, 'tcx>; - fn glb<'a>(&'a self) -> Glb<'a, 'tcx>; + fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx>; + + fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx> { self.fields().infcx } + fn a_is_expected(&self) -> bool { self.fields().a_is_expected } + fn trace(&self) -> TypeTrace<'tcx> { self.fields().trace.clone() } + fn equate<'a>(&'a self) -> Equate<'a, 'tcx> { self.fields().equate() } + fn bivariate<'a>(&'a self) -> Bivariate<'a, 'tcx> { self.fields().bivariate() } + + fn sub<'a>(&'a self) -> Sub<'a, 'tcx> { self.fields().sub() } + fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields().clone()) } + fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields().clone()) } fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>>; - fn contratys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>>; + + fn tys_with_variance(&self, variance: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>) + -> cres<'tcx, Ty<'tcx>>; + fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>>; - fn tps(&self, - _: subst::ParamSpace, - as_: &[Ty<'tcx>], - bs: &[Ty<'tcx>]) - -> cres<'tcx, Vec>> { - // FIXME -- In general, we treat variance a bit wrong - // here. For historical reasons, we treat tps and Self - // as invariant. This is overly conservative. + fn regions_with_variance(&self, variance: ty::Variance, a: ty::Region, b: ty::Region) + -> cres<'tcx, ty::Region>; - if as_.len() != bs.len() { - return Err(ty::terr_ty_param_size(expected_found(self, - as_.len(), - bs.len()))); - } - - try!(as_.iter().zip(bs.iter()) - .map(|(a, b)| self.equate().tys(*a, *b)) - .collect::>>()); - Ok(as_.to_vec()) - } + fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region>; fn substs(&self, item_def_id: ast::DefId, @@ -100,6 +92,11 @@ pub trait Combine<'tcx> : Sized { b_subst: &subst::Substs<'tcx>) -> cres<'tcx, subst::Substs<'tcx>> { + debug!("substs: item_def_id={} a_subst={} b_subst={}", + item_def_id.repr(self.infcx().tcx), + a_subst.repr(self.infcx().tcx), + b_subst.repr(self.infcx().tcx)); + let variances = if self.infcx().tcx.variance_computed.get() { Some(ty::item_variances(self.infcx().tcx, item_def_id)) } else { @@ -119,7 +116,8 @@ pub trait Combine<'tcx> : Sized { for &space in &subst::ParamSpace::all() { let a_tps = a_subst.types.get_slice(space); let b_tps = b_subst.types.get_slice(space); - let tps = try!(self.tps(space, a_tps, b_tps)); + let t_variances = variances.map(|v| v.types.get_slice(space)); + let tps = try!(relate_type_params(self, t_variances, a_tps, b_tps)); substs.types.replace(space, tps); } @@ -132,20 +130,7 @@ pub trait Combine<'tcx> : Sized { for &space in &subst::ParamSpace::all() { let a_regions = a.get_slice(space); let b_regions = b.get_slice(space); - - let mut invariance = Vec::new(); - let r_variances = match variances { - Some(variances) => { - variances.regions.get_slice(space) - } - None => { - for _ in a_regions { - invariance.push(ty::Invariant); - } - &invariance[..] - } - }; - + let r_variances = variances.map(|v| v.regions.get_slice(space)); let regions = try!(relate_region_params(self, r_variances, a_regions, @@ -157,13 +142,34 @@ pub trait Combine<'tcx> : Sized { return Ok(substs); + fn relate_type_params<'tcx, C: Combine<'tcx>>(this: &C, + variances: Option<&[ty::Variance]>, + a_tys: &[Ty<'tcx>], + b_tys: &[Ty<'tcx>]) + -> cres<'tcx, Vec>> + { + if a_tys.len() != b_tys.len() { + return Err(ty::terr_ty_param_size(expected_found(this, + a_tys.len(), + b_tys.len()))); + } + + range(0, a_tys.len()).map(|i| { + let a_ty = a_tys[i]; + let b_ty = b_tys[i]; + let v = variances.map_or(ty::Invariant, |v| v[i]); + this.tys_with_variance(v, a_ty, b_ty) + }).collect() + } + fn relate_region_params<'tcx, C: Combine<'tcx>>(this: &C, - variances: &[ty::Variance], + variances: Option<&[ty::Variance]>, a_rs: &[ty::Region], b_rs: &[ty::Region]) - -> cres<'tcx, Vec> { + -> cres<'tcx, Vec> + { let tcx = this.infcx().tcx; - let num_region_params = variances.len(); + let num_region_params = a_rs.len(); debug!("relate_region_params(\ a_rs={}, \ @@ -173,22 +179,18 @@ pub trait Combine<'tcx> : Sized { b_rs.repr(tcx), variances.repr(tcx)); - assert_eq!(num_region_params, a_rs.len()); + assert_eq!(num_region_params, + variances.map_or(num_region_params, + |v| v.len())); + assert_eq!(num_region_params, b_rs.len()); - let mut rs = vec!(); - for i in 0..num_region_params { + + (0..a_rs.len()).map(|i| { let a_r = a_rs[i]; let b_r = b_rs[i]; - let variance = variances[i]; - let r = match variance { - ty::Invariant => this.equate().regions(a_r, b_r), - ty::Covariant => this.regions(a_r, b_r), - ty::Contravariant => this.contraregions(a_r, b_r), - ty::Bivariant => Ok(a_r), - }; - rs.push(try!(r)); - } - Ok(rs) + let variance = variances.map_or(ty::Invariant, |v| v[i]); + this.regions_with_variance(variance, a_r, b_r) + }).collect() } } @@ -241,7 +243,7 @@ pub trait Combine<'tcx> : Sized { } fn args(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> { - self.contratys(a, b).and_then(|t| Ok(t)) + self.tys_with_variance(ty::Contravariant, a, b).and_then(|t| Ok(t)) } fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety>; @@ -309,7 +311,7 @@ pub trait Combine<'tcx> : Sized { b: &ty::ExistentialBounds<'tcx>) -> cres<'tcx, ty::ExistentialBounds<'tcx>> { - let r = try!(self.contraregions(a.region_bound, b.region_bound)); + let r = try!(self.regions_with_variance(ty::Contravariant, a.region_bound, b.region_bound)); let nb = try!(self.builtin_bounds(a.builtin_bounds, b.builtin_bounds)); let pb = try!(self.projection_bounds(&a.projection_bounds, &b.projection_bounds)); Ok(ty::ExistentialBounds { region_bound: r, @@ -322,11 +324,6 @@ pub trait Combine<'tcx> : Sized { b: ty::BuiltinBounds) -> cres<'tcx, ty::BuiltinBounds>; - fn contraregions(&self, a: ty::Region, b: ty::Region) - -> cres<'tcx, ty::Region>; - - fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region>; - fn trait_refs(&self, a: &ty::TraitRef<'tcx>, b: &ty::TraitRef<'tcx>) @@ -540,7 +537,8 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, } (&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) => { - let r = try!(this.contraregions(*a_r, *b_r)); + let r = try!(this.regions_with_variance(ty::Contravariant, *a_r, *b_r)); + // FIXME(14985) If we have mutable references to trait objects, we // used to use covariant subtyping. I have preserved this behaviour, // even though it is probably incorrect. So don't go down the usual @@ -644,6 +642,10 @@ impl<'f, 'tcx> CombineFields<'f, 'tcx> { Equate((*self).clone()) } + fn bivariate(&self) -> Bivariate<'f, 'tcx> { + Bivariate((*self).clone()) + } + fn sub(&self) -> Sub<'f, 'tcx> { Sub((*self).clone()) } @@ -697,7 +699,7 @@ impl<'f, 'tcx> CombineFields<'f, 'tcx> { EqTo => { self.generalize(a_ty, b_vid, false) } - SupertypeOf | SubtypeOf => { + BiTo | SupertypeOf | SubtypeOf => { self.generalize(a_ty, b_vid, true) } }); @@ -721,6 +723,10 @@ impl<'f, 'tcx> CombineFields<'f, 'tcx> { // to associate causes/spans with each of the relations in // the stack to get this right. match dir { + BiTo => { + try!(self.bivariate().tys(a_ty, b_ty)); + } + EqTo => { try!(self.equate().tys(a_ty, b_ty)); } @@ -730,7 +736,7 @@ impl<'f, 'tcx> CombineFields<'f, 'tcx> { } SupertypeOf => { - try!(self.sub().contratys(a_ty, b_ty)); + try!(self.sub().tys_with_variance(ty::Contravariant, a_ty, b_ty)); } } } diff --git a/src/librustc/middle/infer/equate.rs b/src/librustc/middle/infer/equate.rs index f0bde222864..7194e20b0cf 100644 --- a/src/librustc/middle/infer/equate.rs +++ b/src/librustc/middle/infer/equate.rs @@ -13,11 +13,7 @@ use middle::ty::{self, Ty}; use middle::ty::TyVar; use middle::infer::combine::*; use middle::infer::{cres}; -use middle::infer::glb::Glb; -use middle::infer::InferCtxt; -use middle::infer::lub::Lub; -use middle::infer::sub::Sub; -use middle::infer::{TypeTrace, Subtype}; +use middle::infer::{Subtype}; use middle::infer::type_variable::{EqTo}; use util::ppaux::{Repr}; @@ -33,21 +29,20 @@ pub fn Equate<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Equate<'f, 'tcx> { } impl<'f, 'tcx> Combine<'tcx> for Equate<'f, 'tcx> { - fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx> { self.fields.infcx } - fn tag(&self) -> String { "eq".to_string() } - fn a_is_expected(&self) -> bool { self.fields.a_is_expected } - fn trace(&self) -> TypeTrace<'tcx> { self.fields.trace.clone() } + fn tag(&self) -> String { "Equate".to_string() } + fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields } - fn equate<'a>(&'a self) -> Equate<'a, 'tcx> { Equate(self.fields.clone()) } - fn sub<'a>(&'a self) -> Sub<'a, 'tcx> { Sub(self.fields.clone()) } - fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields.clone()) } - fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields.clone()) } - - fn contratys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> { + fn tys_with_variance(&self, _: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>) + -> cres<'tcx, Ty<'tcx>> + { + // Once we're equating, it doesn't matter what the variance is. self.tys(a, b) } - fn contraregions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> { + fn regions_with_variance(&self, _: ty::Variance, a: ty::Region, b: ty::Region) + -> cres<'tcx, ty::Region> + { + // Once we're equating, it doesn't matter what the variance is. self.regions(a, b) } diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 9aafa1f9fd2..53032f9b9ac 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -675,6 +675,17 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { sup, ""); } + infer::Operand(span) => { + self.tcx.sess.span_err( + span, + "lifetime of operand does not outlive \ + the operation"); + note_and_explain_region( + self.tcx, + "the operand is only valid for ", + sup, + ""); + } infer::AddrOf(span) => { self.tcx.sess.span_err( span, @@ -1593,6 +1604,11 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { span, "...so that return value is valid for the call"); } + infer::Operand(span) => { + self.tcx.sess.span_err( + span, + "...so that operand is valid for operation"); + } infer::AddrOf(span) => { self.tcx.sess.span_note( span, diff --git a/src/librustc/middle/infer/glb.rs b/src/librustc/middle/infer/glb.rs index ff0c2d92f45..33303808e84 100644 --- a/src/librustc/middle/infer/glb.rs +++ b/src/librustc/middle/infer/glb.rs @@ -10,12 +10,9 @@ use super::combine::*; use super::lattice::*; -use super::equate::Equate; use super::higher_ranked::HigherRankedRelations; -use super::lub::Lub; -use super::sub::Sub; -use super::{cres, InferCtxt}; -use super::{TypeTrace, Subtype}; +use super::{cres}; +use super::Subtype; use middle::ty::{BuiltinBounds}; use middle::ty::{self, Ty}; @@ -34,15 +31,30 @@ pub fn Glb<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Glb<'f, 'tcx> { } impl<'f, 'tcx> Combine<'tcx> for Glb<'f, 'tcx> { - fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx> { self.fields.infcx } - fn tag(&self) -> String { "glb".to_string() } - fn a_is_expected(&self) -> bool { self.fields.a_is_expected } - fn trace(&self) -> TypeTrace<'tcx> { self.fields.trace.clone() } + fn tag(&self) -> String { "Glb".to_string() } + fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields } - fn equate<'a>(&'a self) -> Equate<'a, 'tcx> { Equate(self.fields.clone()) } - fn sub<'a>(&'a self) -> Sub<'a, 'tcx> { Sub(self.fields.clone()) } - fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields.clone()) } - fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields.clone()) } + fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>) + -> cres<'tcx, Ty<'tcx>> + { + match v { + ty::Invariant => self.equate().tys(a, b), + ty::Covariant => self.tys(a, b), + ty::Bivariant => self.bivariate().tys(a, b), + ty::Contravariant => self.lub().tys(a, b), + } + } + + fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region) + -> cres<'tcx, ty::Region> + { + match v { + ty::Invariant => self.equate().regions(a, b), + ty::Covariant => self.regions(a, b), + ty::Bivariant => self.bivariate().regions(a, b), + ty::Contravariant => self.lub().regions(a, b), + } + } fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>> { let tcx = self.fields.infcx.tcx; @@ -75,10 +87,6 @@ impl<'f, 'tcx> Combine<'tcx> for Glb<'f, 'tcx> { } } - fn contratys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> { - self.lub().tys(a, b) - } - fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> { match (a, b) { (Unsafety::Normal, _) | (_, Unsafety::Normal) => Ok(Unsafety::Normal), @@ -104,11 +112,6 @@ impl<'f, 'tcx> Combine<'tcx> for Glb<'f, 'tcx> { Ok(self.fields.infcx.region_vars.glb_regions(Subtype(self.trace()), a, b)) } - fn contraregions(&self, a: ty::Region, b: ty::Region) - -> cres<'tcx, ty::Region> { - self.lub().regions(a, b) - } - fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> { super_lattice_tys(self, a, b) } diff --git a/src/librustc/middle/infer/higher_ranked/mod.rs b/src/librustc/middle/infer/higher_ranked/mod.rs index 4469e27a5b0..a729156c88b 100644 --- a/src/librustc/middle/infer/higher_ranked/mod.rs +++ b/src/librustc/middle/infer/higher_ranked/mod.rs @@ -31,7 +31,7 @@ pub trait HigherRankedRelations<'tcx> { where T : Combineable<'tcx>; } -trait InferCtxtExt<'tcx> { +trait InferCtxtExt { fn tainted_regions(&self, snapshot: &CombinedSnapshot, r: ty::Region) -> Vec; fn region_vars_confined_to_snapshot(&self, @@ -371,7 +371,7 @@ fn fold_regions_in<'tcx, T, F>(tcx: &ty::ctxt<'tcx>, })) } -impl<'a,'tcx> InferCtxtExt<'tcx> for InferCtxt<'a,'tcx> { +impl<'a,'tcx> InferCtxtExt for InferCtxt<'a,'tcx> { fn tainted_regions(&self, snapshot: &CombinedSnapshot, r: ty::Region) -> Vec { self.region_vars.tainted(&snapshot.region_vars_snapshot, r) } diff --git a/src/librustc/middle/infer/lub.rs b/src/librustc/middle/infer/lub.rs index 204560e87ee..3570effa9fa 100644 --- a/src/librustc/middle/infer/lub.rs +++ b/src/librustc/middle/infer/lub.rs @@ -9,13 +9,10 @@ // except according to those terms. use super::combine::*; -use super::equate::Equate; -use super::glb::Glb; use super::higher_ranked::HigherRankedRelations; use super::lattice::*; -use super::sub::Sub; -use super::{cres, InferCtxt}; -use super::{TypeTrace, Subtype}; +use super::{cres}; +use super::{Subtype}; use middle::ty::{BuiltinBounds}; use middle::ty::{self, Ty}; @@ -34,15 +31,30 @@ pub fn Lub<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Lub<'f, 'tcx> { } impl<'f, 'tcx> Combine<'tcx> for Lub<'f, 'tcx> { - fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx> { self.fields.infcx } - fn tag(&self) -> String { "lub".to_string() } - fn a_is_expected(&self) -> bool { self.fields.a_is_expected } - fn trace(&self) -> TypeTrace<'tcx> { self.fields.trace.clone() } + fn tag(&self) -> String { "Lub".to_string() } + fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields } - fn equate<'a>(&'a self) -> Equate<'a, 'tcx> { Equate(self.fields.clone()) } - fn sub<'a>(&'a self) -> Sub<'a, 'tcx> { Sub(self.fields.clone()) } - fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields.clone()) } - fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields.clone()) } + fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>) + -> cres<'tcx, Ty<'tcx>> + { + match v { + ty::Invariant => self.equate().tys(a, b), + ty::Covariant => self.tys(a, b), + ty::Bivariant => self.bivariate().tys(a, b), + ty::Contravariant => self.glb().tys(a, b), + } + } + + fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region) + -> cres<'tcx, ty::Region> + { + match v { + ty::Invariant => self.equate().regions(a, b), + ty::Covariant => self.regions(a, b), + ty::Bivariant => self.bivariate().regions(a, b), + ty::Contravariant => self.glb().regions(a, b), + } + } fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>> { let tcx = self.tcx(); @@ -70,10 +82,6 @@ impl<'f, 'tcx> Combine<'tcx> for Lub<'f, 'tcx> { } } - fn contratys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> { - self.glb().tys(a, b) - } - fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> { match (a, b) { (Unsafety::Unsafe, _) | (_, Unsafety::Unsafe) => Ok(Unsafety::Unsafe), @@ -90,11 +98,6 @@ impl<'f, 'tcx> Combine<'tcx> for Lub<'f, 'tcx> { Ok(a.intersection(b)) } - fn contraregions(&self, a: ty::Region, b: ty::Region) - -> cres<'tcx, ty::Region> { - self.glb().regions(a, b) - } - fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> { debug!("{}.regions({}, {})", self.tag(), diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 00e377d65fe..b0576ff55ff 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -45,6 +45,7 @@ use self::lub::Lub; use self::unify::{UnificationTable, InferCtxtMethodsForSimplyUnifiableTypes}; use self::error_reporting::ErrorReporting; +pub mod bivariate; pub mod combine; pub mod equate; pub mod error_reporting; @@ -209,6 +210,9 @@ pub enum SubregionOrigin<'tcx> { // Region in return type of invoked fn must enclose call CallReturn(Span), + // Operands must be in scope + Operand(Span), + // Region resulting from a `&` expr must enclose the `&` expr AddrOf(Span), @@ -1194,6 +1198,7 @@ impl<'tcx> SubregionOrigin<'tcx> { CallRcvr(a) => a, CallArg(a) => a, CallReturn(a) => a, + Operand(a) => a, AddrOf(a) => a, AutoBorrow(a) => a, SafeDestructor(a) => a, @@ -1257,6 +1262,7 @@ impl<'tcx> Repr<'tcx> for SubregionOrigin<'tcx> { CallRcvr(a) => format!("CallRcvr({})", a.repr(tcx)), CallArg(a) => format!("CallArg({})", a.repr(tcx)), CallReturn(a) => format!("CallReturn({})", a.repr(tcx)), + Operand(a) => format!("Operand({})", a.repr(tcx)), AddrOf(a) => format!("AddrOf({})", a.repr(tcx)), AutoBorrow(a) => format!("AutoBorrow({})", a.repr(tcx)), SafeDestructor(a) => format!("SafeDestructor({})", a.repr(tcx)), diff --git a/src/librustc/middle/infer/sub.rs b/src/librustc/middle/infer/sub.rs index 1e0d14544ff..33da3092b2a 100644 --- a/src/librustc/middle/infer/sub.rs +++ b/src/librustc/middle/infer/sub.rs @@ -10,12 +10,8 @@ use super::combine::*; use super::{cres, CresCompare}; -use super::equate::Equate; -use super::glb::Glb; use super::higher_ranked::HigherRankedRelations; -use super::InferCtxt; -use super::lub::Lub; -use super::{TypeTrace, Subtype}; +use super::{Subtype}; use super::type_variable::{SubtypeOf, SupertypeOf}; use middle::ty::{BuiltinBounds}; @@ -37,28 +33,30 @@ pub fn Sub<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Sub<'f, 'tcx> { } impl<'f, 'tcx> Combine<'tcx> for Sub<'f, 'tcx> { - fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx> { self.fields.infcx } - fn tag(&self) -> String { "sub".to_string() } - fn a_is_expected(&self) -> bool { self.fields.a_is_expected } - fn trace(&self) -> TypeTrace<'tcx> { self.fields.trace.clone() } + fn tag(&self) -> String { "Sub".to_string() } + fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields } - fn equate<'a>(&'a self) -> Equate<'a, 'tcx> { Equate(self.fields.clone()) } - fn sub<'a>(&'a self) -> Sub<'a, 'tcx> { Sub(self.fields.clone()) } - fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields.clone()) } - fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields.clone()) } - - fn contratys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> { - Sub(self.fields.switch_expected()).tys(b, a) + fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>) + -> cres<'tcx, Ty<'tcx>> + { + match v { + ty::Invariant => self.equate().tys(a, b), + ty::Covariant => self.tys(a, b), + ty::Bivariant => self.bivariate().tys(a, b), + ty::Contravariant => Sub(self.fields.switch_expected()).tys(b, a), + } } - fn contraregions(&self, a: ty::Region, b: ty::Region) - -> cres<'tcx, ty::Region> { - let opp = CombineFields { - a_is_expected: !self.fields.a_is_expected, - ..self.fields.clone() - }; - Sub(opp).regions(b, a) - } + fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region) + -> cres<'tcx, ty::Region> + { + match v { + ty::Invariant => self.equate().regions(a, b), + ty::Covariant => self.regions(a, b), + ty::Bivariant => self.bivariate().regions(a, b), + ty::Contravariant => Sub(self.fields.switch_expected()).regions(b, a), + } + } fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> { debug!("{}.regions({}, {})", diff --git a/src/librustc/middle/infer/type_variable.rs b/src/librustc/middle/infer/type_variable.rs index 9b8a4a84412..a856137af09 100644 --- a/src/librustc/middle/infer/type_variable.rs +++ b/src/librustc/middle/infer/type_variable.rs @@ -14,6 +14,7 @@ use self::UndoEntry::*; use middle::ty::{self, Ty}; use std::cmp::min; +use std::marker::PhantomData; use std::mem; use std::u32; use util::snapshot_vec as sv; @@ -42,13 +43,13 @@ enum UndoEntry { Relate(ty::TyVid, ty::TyVid), } -struct Delegate<'tcx>; +struct Delegate<'tcx>(PhantomData<&'tcx ()>); type Relation = (RelationDir, ty::TyVid); #[derive(Copy, PartialEq, Debug)] pub enum RelationDir { - SubtypeOf, SupertypeOf, EqTo + SubtypeOf, SupertypeOf, EqTo, BiTo } impl RelationDir { @@ -56,14 +57,15 @@ impl RelationDir { match self { SubtypeOf => SupertypeOf, SupertypeOf => SubtypeOf, - EqTo => EqTo + EqTo => EqTo, + BiTo => BiTo, } } } impl<'tcx> TypeVariableTable<'tcx> { pub fn new() -> TypeVariableTable<'tcx> { - TypeVariableTable { values: sv::SnapshotVec::new(Delegate) } + TypeVariableTable { values: sv::SnapshotVec::new(Delegate(PhantomData)) } } fn relations<'a>(&'a mut self, a: ty::TyVid) -> &'a mut Vec { diff --git a/src/librustc/middle/infer/unify.rs b/src/librustc/middle/infer/unify.rs index 235f3f994c6..0675cec6f69 100644 --- a/src/librustc/middle/infer/unify.rs +++ b/src/librustc/middle/infer/unify.rs @@ -18,6 +18,7 @@ use middle::infer::{uok, ures}; use middle::infer::InferCtxt; use std::cell::RefCell; use std::fmt::Debug; +use std::marker::PhantomData; use syntax::ast; use util::snapshot_vec as sv; @@ -79,7 +80,7 @@ pub struct UnificationTable { /// made during the snapshot may either be *committed* or *rolled back*. pub struct Snapshot { // Link snapshot to the key type `K` of the table. - marker: marker::CovariantType, + marker: marker::PhantomData, snapshot: sv::Snapshot, } @@ -92,7 +93,7 @@ pub struct Node { } #[derive(Copy)] -pub struct Delegate; +pub struct Delegate(PhantomData); // We can't use V:LatticeValue, much as I would like to, // because frequently the pattern is that V=Option for some @@ -102,14 +103,14 @@ pub struct Delegate; impl UnificationTable { pub fn new() -> UnificationTable { UnificationTable { - values: sv::SnapshotVec::new(Delegate), + values: sv::SnapshotVec::new(Delegate(PhantomData)), } } /// Starts a new snapshot. Each snapshot must be either /// rolled back or committed in a "LIFO" (stack) order. pub fn snapshot(&mut self) -> Snapshot { - Snapshot { marker: marker::CovariantType::, + Snapshot { marker: marker::PhantomData::, snapshot: self.values.start_snapshot() } } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index fd641bd709d..56c5928a132 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -306,12 +306,13 @@ lets_do_this! { ExchangeHeapLangItem, "exchange_heap", exchange_heap; OwnedBoxLangItem, "owned_box", owned_box; + PhantomFnItem, "phantom_fn", phantom_fn; PhantomDataItem, "phantom_data", phantom_data; + // Deprecated: CovariantTypeItem, "covariant_type", covariant_type; ContravariantTypeItem, "contravariant_type", contravariant_type; InvariantTypeItem, "invariant_type", invariant_type; - CovariantLifetimeItem, "covariant_lifetime", covariant_lifetime; ContravariantLifetimeItem, "contravariant_lifetime", contravariant_lifetime; InvariantLifetimeItem, "invariant_lifetime", invariant_lifetime; diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs index 3a7522cafee..e199a60c370 100644 --- a/src/librustc/middle/traits/coherence.rs +++ b/src/librustc/middle/traits/coherence.rs @@ -10,24 +10,27 @@ //! See `doc.rs` for high-level documentation +use super::Normalized; use super::SelectionContext; -use super::{Obligation, ObligationCause}; +use super::{ObligationCause}; +use super::PredicateObligation; use super::project; use super::util; use middle::subst::{Subst, TypeSpace}; -use middle::ty::{self, Ty}; -use middle::infer::InferCtxt; +use middle::ty::{self, ToPolyTraitRef, Ty}; +use middle::infer::{self, InferCtxt}; use std::collections::HashSet; use std::rc::Rc; use syntax::ast; use syntax::codemap::DUMMY_SP; use util::ppaux::Repr; -pub fn impl_can_satisfy(infcx: &InferCtxt, - impl1_def_id: ast::DefId, - impl2_def_id: ast::DefId) - -> bool +/// True if there exist types that satisfy both of the two given impls. +pub fn overlapping_impls(infcx: &InferCtxt, + impl1_def_id: ast::DefId, + impl2_def_id: ast::DefId) + -> bool { debug!("impl_can_satisfy(\ impl1_def_id={}, \ @@ -35,28 +38,68 @@ pub fn impl_can_satisfy(infcx: &InferCtxt, impl1_def_id.repr(infcx.tcx), impl2_def_id.repr(infcx.tcx)); - let param_env = ty::empty_parameter_environment(infcx.tcx); - let mut selcx = SelectionContext::intercrate(infcx, ¶m_env); - let cause = ObligationCause::dummy(); + let param_env = &ty::empty_parameter_environment(infcx.tcx); + let selcx = &mut SelectionContext::intercrate(infcx, param_env); + infcx.probe(|_| { + overlap(selcx, impl1_def_id, impl2_def_id) || overlap(selcx, impl2_def_id, impl1_def_id) + }) +} - // `impl1` provides an implementation of `Foo for Z`. - let impl1_substs = - util::fresh_substs_for_impl(infcx, DUMMY_SP, impl1_def_id); - let impl1_trait_ref = - (*ty::impl_trait_ref(infcx.tcx, impl1_def_id).unwrap()).subst(infcx.tcx, &impl1_substs); - let impl1_trait_ref = - project::normalize(&mut selcx, cause.clone(), &impl1_trait_ref); +/// Can the types from impl `a` be used to satisfy impl `b`? +/// (Including all conditions) +fn overlap(selcx: &mut SelectionContext, + a_def_id: ast::DefId, + b_def_id: ast::DefId) + -> bool +{ + let (a_trait_ref, a_obligations) = impl_trait_ref_and_oblig(selcx, a_def_id); + let (b_trait_ref, b_obligations) = impl_trait_ref_and_oblig(selcx, b_def_id); - // Determine whether `impl2` can provide an implementation for those - // same types. - let obligation = Obligation::new(cause, - ty::Binder(ty::TraitPredicate { - trait_ref: Rc::new(impl1_trait_ref.value), - })); - debug!("impl_can_satisfy(obligation={})", obligation.repr(infcx.tcx)); - selcx.evaluate_impl(impl2_def_id, &obligation) && - impl1_trait_ref.obligations.iter().all( - |o| selcx.evaluate_obligation(o)) + // Does `a <: b` hold? If not, no overlap. + if let Err(_) = infer::mk_sub_poly_trait_refs(selcx.infcx(), + true, + infer::Misc(DUMMY_SP), + a_trait_ref.to_poly_trait_ref(), + b_trait_ref.to_poly_trait_ref()) { + return false; + } + + // Are any of the obligations unsatisfiable? If so, no overlap. + a_obligations.iter() + .chain(b_obligations.iter()) + .all(|o| selcx.evaluate_obligation(o)) +} + +/// Instantiate fresh variables for all bound parameters of the impl +/// and return the impl trait ref with those variables substituted. +fn impl_trait_ref_and_oblig<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, + impl_def_id: ast::DefId) + -> (Rc>, + Vec>) +{ + let impl_substs = + &util::fresh_substs_for_impl(selcx.infcx(), DUMMY_SP, impl_def_id); + let impl_trait_ref = + ty::impl_trait_ref(selcx.tcx(), impl_def_id).unwrap(); + let impl_trait_ref = + impl_trait_ref.subst(selcx.tcx(), impl_substs); + let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } = + project::normalize(selcx, ObligationCause::dummy(), &impl_trait_ref); + + let predicates = ty::lookup_predicates(selcx.tcx(), impl_def_id); + let predicates = predicates.instantiate(selcx.tcx(), impl_substs); + let Normalized { value: predicates, obligations: normalization_obligations2 } = + project::normalize(selcx, ObligationCause::dummy(), &predicates); + let impl_obligations = + util::predicates_for_generics(selcx.tcx(), ObligationCause::dummy(), 0, &predicates); + + let impl_obligations: Vec<_> = + impl_obligations.into_iter() + .chain(normalization_obligations1.into_iter()) + .chain(normalization_obligations2.into_iter()) + .collect(); + + (impl_trait_ref, impl_obligations) } pub enum OrphanCheckErr<'tcx> { diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 57c9fa7a4d9..a63dcfc24a1 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -28,6 +28,7 @@ use util::ppaux::{Repr, UserString}; pub use self::error_reporting::report_fulfillment_errors; pub use self::error_reporting::suggest_new_overflow_limit; pub use self::coherence::orphan_check; +pub use self::coherence::overlapping_impls; pub use self::coherence::OrphanCheckErr; pub use self::fulfill::{FulfillmentContext, RegionObligation}; pub use self::project::MismatchedProjectionTypes; @@ -270,16 +271,6 @@ pub struct VtableObjectData<'tcx> { pub object_ty: Ty<'tcx>, } -/// True if there exist types that satisfy both of the two given impls. -pub fn overlapping_impls(infcx: &InferCtxt, - impl1_def_id: ast::DefId, - impl2_def_id: ast::DefId) - -> bool -{ - coherence::impl_can_satisfy(infcx, impl1_def_id, impl2_def_id) && - coherence::impl_can_satisfy(infcx, impl2_def_id, impl1_def_id) -} - /// Creates predicate obligations from the generic bounds. pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>, cause: ObligationCause<'tcx>, diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 496ce6be75c..0e298920841 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -132,6 +132,7 @@ pub enum MethodMatchedData { /// parameters) that would have to be inferred from the impl. #[derive(PartialEq,Eq,Debug,Clone)] enum SelectionCandidate<'tcx> { + PhantomFnCandidate, BuiltinCandidate(ty::BuiltinBound), ParamCandidate(ty::PolyTraitRef<'tcx>), ImplCandidate(ast::DefId), @@ -793,8 +794,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { stack: &TraitObligationStack<'o, 'tcx>) -> Result, SelectionError<'tcx>> { - // Check for overflow. - let TraitObligationStack { obligation, .. } = *stack; let mut candidates = SelectionCandidateSet { @@ -802,6 +801,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ambiguous: false }; + // Check for the `PhantomFn` trait. This is really just a + // special annotation that is *always* considered to match, no + // matter what the type parameters are etc. + if self.tcx().lang_items.phantom_fn() == Some(obligation.predicate.def_id()) { + candidates.vec.push(PhantomFnCandidate); + return Ok(candidates); + } + // Other bounds. Consider both in-scope bounds from fn decl // and applicable impls. There is a certain set of precedence rules here. @@ -1629,6 +1636,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { try!(self.confirm_builtin_candidate(obligation, builtin_bound)))) } + PhantomFnCandidate | ErrorCandidate => { Ok(VtableBuiltin(VtableBuiltinData { nested: VecPerParamSpace::empty() })) } @@ -2295,6 +2303,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { match *self { + PhantomFnCandidate => format!("PhantomFnCandidate"), ErrorCandidate => format!("ErrorCandidate"), BuiltinCandidate(b) => format!("BuiltinCandidate({:?})", b), ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)), diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index b1ea89c6574..e9908397f97 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3008,6 +3008,13 @@ impl<'tcx> TyS<'tcx> { assert_eq!(r, Some(self)); walker } + + pub fn as_opt_param_ty(&self) -> Option { + match self.sty { + ty::ty_param(ref d) => Some(d.clone()), + _ => None, + } + } } pub fn walk_ty<'tcx, F>(ty_root: Ty<'tcx>, mut f: F) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 0494e1f7686..1639772103b 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -306,10 +306,10 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> { // Crate-local: // // meh. - struct Visitor<'a, 'b: 'a, 'tcx: 'a + 'b> { + struct Visitor<'a> { traits: &'a mut AllTraitsVec, } - impl<'v,'a, 'b, 'tcx> visit::Visitor<'v> for Visitor<'a, 'b, 'tcx> { + impl<'v, 'a> visit::Visitor<'v> for Visitor<'a> { fn visit_item(&mut self, i: &'v ast::Item) { match i.node { ast::ItemTrait(..) => { diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 44a3b5167c7..82abff8c425 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -626,6 +626,20 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { visit::walk_expr(rcx, expr); } + ast::ExprBinary(_, ref lhs, ref rhs) => { + // If you do `x OP y`, then the types of `x` and `y` must + // outlive the operation you are performing. + let lhs_ty = rcx.resolve_expr_type_adjusted(&**lhs); + let rhs_ty = rcx.resolve_expr_type_adjusted(&**rhs); + for &ty in [lhs_ty, rhs_ty].iter() { + type_must_outlive(rcx, + infer::Operand(expr.span), + ty, + ty::ReScope(CodeExtent::from_node_id(expr.id))); + } + visit::walk_expr(rcx, expr); + } + ast::ExprUnary(op, ref lhs) if has_method_map => { let implicitly_ref_args = !ast_util::is_by_value_unop(op); diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index d124282d391..2601c4d2752 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -10,21 +10,22 @@ use astconv::AstConv; use check::{FnCtxt, Inherited, blank_fn_ctxt, vtable, regionck}; +use constrained_type_params::identify_constrained_type_params; use CrateCtxt; use middle::region; -use middle::subst; +use middle::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace}; use middle::traits; use middle::ty::{self, Ty}; use middle::ty::liberate_late_bound_regions; use middle::ty_fold::{TypeFolder, TypeFoldable, super_fold_ty}; -use util::ppaux::Repr; +use util::ppaux::{Repr, UserString}; use std::collections::HashSet; use syntax::ast; use syntax::ast_util::{local_def}; use syntax::attr; use syntax::codemap::Span; -use syntax::parse::token; +use syntax::parse::token::{self, special_idents}; use syntax::visit; use syntax::visit::Visitor; @@ -38,6 +39,10 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { CheckTypeWellFormedVisitor { ccx: ccx, cache: HashSet::new() } } + fn tcx(&self) -> &ty::ctxt<'tcx> { + self.ccx.tcx + } + /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are /// well-formed, meaning that they do not require any constraints not declared in the struct /// definition itself. For example, this definition would be illegal: @@ -96,19 +101,29 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { ast::ItemConst(..) => { self.check_item_type(item); } - ast::ItemStruct(ref struct_def, _) => { - self.check_type_defn(item, |fcx| vec![struct_variant(fcx, &**struct_def)]); + ast::ItemStruct(ref struct_def, ref ast_generics) => { + self.check_type_defn(item, |fcx| { + vec![struct_variant(fcx, &**struct_def)] + }); + + self.check_variances_for_type_defn(item, ast_generics); } - ast::ItemEnum(ref enum_def, _) => { - self.check_type_defn(item, |fcx| enum_variants(fcx, enum_def)); + ast::ItemEnum(ref enum_def, ref ast_generics) => { + self.check_type_defn(item, |fcx| { + enum_variants(fcx, enum_def) + }); + + self.check_variances_for_type_defn(item, ast_generics); } - ast::ItemTrait(..) => { + ast::ItemTrait(_, ref ast_generics, _, _) => { let trait_predicates = ty::lookup_predicates(ccx.tcx, local_def(item.id)); reject_non_type_param_bounds( ccx.tcx, item.span, &trait_predicates); + self.check_variances(item, ast_generics, &trait_predicates, + self.tcx().lang_items.phantom_fn()); } _ => {} } @@ -276,6 +291,123 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { } }); } + + fn check_variances_for_type_defn(&self, + item: &ast::Item, + ast_generics: &ast::Generics) + { + let item_def_id = local_def(item.id); + let predicates = ty::lookup_predicates(self.tcx(), item_def_id); + self.check_variances(item, + ast_generics, + &predicates, + self.tcx().lang_items.phantom_data()); + } + + fn check_variances(&self, + item: &ast::Item, + ast_generics: &ast::Generics, + ty_predicates: &ty::GenericPredicates<'tcx>, + suggested_marker_id: Option) + { + let variance_lang_items = &[ + self.tcx().lang_items.phantom_fn(), + self.tcx().lang_items.phantom_data(), + ]; + + let item_def_id = local_def(item.id); + let is_lang_item = variance_lang_items.iter().any(|n| *n == Some(item_def_id)); + if is_lang_item { + return; + } + + let variances = ty::item_variances(self.tcx(), item_def_id); + + let mut constrained_parameters: HashSet<_> = + variances.types + .iter_enumerated() + .filter(|&(_, _, &variance)| variance != ty::Bivariant) + .map(|(space, index, _)| self.param_ty(ast_generics, space, index)) + .collect(); + + identify_constrained_type_params(self.tcx(), + ty_predicates.predicates.as_slice(), + None, + &mut constrained_parameters); + + for (space, index, _) in variances.types.iter_enumerated() { + let param_ty = self.param_ty(ast_generics, space, index); + if constrained_parameters.contains(¶m_ty) { + continue; + } + let span = self.ty_param_span(ast_generics, item, space, index); + self.report_bivariance(span, param_ty.name, suggested_marker_id); + } + + for (space, index, &variance) in variances.regions.iter_enumerated() { + if variance != ty::Bivariant { + continue; + } + + assert_eq!(space, TypeSpace); + let span = ast_generics.lifetimes[index].lifetime.span; + let name = ast_generics.lifetimes[index].lifetime.name; + self.report_bivariance(span, name, suggested_marker_id); + } + } + + fn param_ty(&self, + ast_generics: &ast::Generics, + space: ParamSpace, + index: usize) + -> ty::ParamTy + { + let name = match space { + TypeSpace => ast_generics.ty_params[index].ident.name, + SelfSpace => special_idents::type_self.name, + FnSpace => self.tcx().sess.bug("Fn space occupied?"), + }; + + ty::ParamTy { space: space, idx: index as u32, name: name } + } + + fn ty_param_span(&self, + ast_generics: &ast::Generics, + item: &ast::Item, + space: ParamSpace, + index: usize) + -> Span + { + match space { + TypeSpace => ast_generics.ty_params[index].span, + SelfSpace => item.span, + FnSpace => self.tcx().sess.span_bug(item.span, "Fn space occupied?"), + } + } + + fn report_bivariance(&self, + span: Span, + param_name: ast::Name, + suggested_marker_id: Option) + { + self.tcx().sess.span_err( + span, + &format!("parameter `{}` is never used", + param_name.user_string(self.tcx()))[]); + + match suggested_marker_id { + Some(def_id) => { + self.tcx().sess.span_help( + span, + format!("consider removing `{}` or using a marker such as `{}`", + param_name.user_string(self.tcx()), + ty::item_path_str(self.tcx(), def_id)).as_slice()); + } + None => { + // no lang items, no help! + } + } + } } // Reject any predicates that do not involve a type parameter. @@ -343,9 +475,9 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> { match fk { visit::FkFnBlock | visit::FkItemFn(..) => {} visit::FkMethod(..) => { - match ty::impl_or_trait_item(self.ccx.tcx, local_def(id)) { + match ty::impl_or_trait_item(self.tcx(), local_def(id)) { ty::ImplOrTraitItem::MethodTraitItem(ty_method) => { - reject_shadowing_type_parameters(self.ccx.tcx, span, &ty_method.generics) + reject_shadowing_type_parameters(self.tcx(), span, &ty_method.generics) } _ => {} } @@ -359,14 +491,14 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> { &ast::TraitItem::ProvidedMethod(_) | &ast::TraitItem::TypeTraitItem(_) => {}, &ast::TraitItem::RequiredMethod(ref method) => { - match ty::impl_or_trait_item(self.ccx.tcx, local_def(method.id)) { + match ty::impl_or_trait_item(self.tcx(), local_def(method.id)) { ty::ImplOrTraitItem::MethodTraitItem(ty_method) => { reject_non_type_param_bounds( - self.ccx.tcx, + self.tcx(), method.span, &ty_method.predicates); reject_shadowing_type_parameters( - self.ccx.tcx, + self.tcx(), method.span, &ty_method.generics); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 833daf083a7..0b78af18e26 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -87,6 +87,7 @@ There are some shortcomings in this design: use astconv::{self, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region}; use middle::def; +use constrained_type_params::identify_constrained_type_params; use middle::lang_items::SizedTraitLangItem; use middle::region; use middle::resolve_lifetime; @@ -1960,51 +1961,15 @@ fn enforce_impl_ty_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>, let mut input_parameters: HashSet<_> = impl_trait_ref.iter() .flat_map(|t| t.input_types().iter()) // Types in trait ref, if any - .chain(Some(impl_scheme.ty).iter()) // Self type, always + .chain(Some(impl_scheme.ty).iter()) // Self type, always .flat_map(|t| t.walk()) - .filter_map(to_opt_param_ty) + .filter_map(|t| t.as_opt_param_ty()) .collect(); - loop { - let num_inputs = input_parameters.len(); - - let projection_predicates = - impl_predicates.predicates - .iter() - .filter_map(|predicate| { - match *predicate { - // Ignore higher-ranked binders. For the purposes - // of this check, they don't matter because they - // only affect named regions, and we're just - // concerned about type parameters here. - ty::Predicate::Projection(ref data) => Some(data.0.clone()), - _ => None, - } - }); - - for projection in projection_predicates { - // Special case: watch out for some kind of sneaky attempt - // to project out an associated type defined by this very trait. - if Some(projection.projection_ty.trait_ref.clone()) == impl_trait_ref { - continue; - } - - let relies_only_on_inputs = - projection.projection_ty.trait_ref.input_types().iter() - .flat_map(|t| t.walk()) - .filter_map(to_opt_param_ty) - .all(|t| input_parameters.contains(&t)); - - if relies_only_on_inputs { - input_parameters.extend( - projection.ty.walk().filter_map(to_opt_param_ty)); - } - } - - if input_parameters.len() == num_inputs { - break; - } - } + identify_constrained_type_params(tcx, + impl_predicates.predicates.as_slice(), + impl_trait_ref, + &mut input_parameters); for (index, ty_param) in ast_generics.ty_params.iter().enumerate() { let param_ty = ty::ParamTy { space: TypeSpace, @@ -2025,11 +1990,4 @@ fn enforce_impl_ty_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>, } } } - - fn to_opt_param_ty<'tcx>(ty: Ty<'tcx>) -> Option { - match ty.sty { - ty::ty_param(ref d) => Some(d.clone()), - _ => None, - } - } } diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs new file mode 100644 index 00000000000..83d7e985000 --- /dev/null +++ b/src/librustc_typeck/constrained_type_params.rs @@ -0,0 +1,61 @@ +// 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 middle::ty::{self}; + +use std::collections::HashSet; +use std::rc::Rc; + +pub fn identify_constrained_type_params<'tcx>(_tcx: &ty::ctxt<'tcx>, + predicates: &[ty::Predicate<'tcx>], + impl_trait_ref: Option>>, + input_parameters: &mut HashSet) +{ + loop { + let num_inputs = input_parameters.len(); + + let projection_predicates = + predicates.iter() + .filter_map(|predicate| { + match *predicate { + // Ignore higher-ranked binders. For the purposes + // of this check, they don't matter because they + // only affect named regions, and we're just + // concerned about type parameters here. + ty::Predicate::Projection(ref data) => Some(data.0.clone()), + _ => None, + } + }); + + for projection in projection_predicates { + // Special case: watch out for some kind of sneaky attempt + // to project out an associated type defined by this very trait. + if Some(projection.projection_ty.trait_ref.clone()) == impl_trait_ref { + continue; + } + + let relies_only_on_inputs = + projection.projection_ty.trait_ref.input_types() + .iter() + .flat_map(|t| t.walk()) + .filter_map(|t| t.as_opt_param_ty()) + .all(|t| input_parameters.contains(&t)); + + if relies_only_on_inputs { + input_parameters.extend( + projection.ty.walk().filter_map(|t| t.as_opt_param_ty())); + } + } + + if input_parameters.len() == num_inputs { + break; + } + } +} diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 7498dc8179d..b5dca0bd4f6 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -123,6 +123,7 @@ mod check; mod rscope; mod astconv; mod collect; +mod constrained_type_params; mod coherence; mod variance; diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index bf29bcd5123..1adcf133bf3 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -187,6 +187,22 @@ //! and the definition-site variance of the [corresponding] type parameter //! of a class `C` is `V1`, then the variance of `X` in the type expression //! `C` is `V3 = V1.xform(V2)`. +//! +//! ### Constraints +//! +//! If I have a struct or enum with where clauses: +//! +//! struct Foo { ... } +//! +//! you might wonder whether the variance of `T` with respect to `Bar` +//! affects the variance `T` with respect to `Foo`. I claim no. The +//! reason: assume that `T` is invariant w/r/t `Bar` but covariant w/r/t +//! `Foo`. And then we have a `Foo` that is upcast to `Foo`, where +//! `X <: Y`. However, while `X : Bar`, `Y : Bar` does not hold. In that +//! case, the upcast will be illegal, but not because of a variance +//! failure, but rather because the target type `Foo` is itself just +//! not well-formed. Basically we get to assume well-formedness of all +//! types involved before considering variance. use self::VarianceTerm::*; use self::ParamKind::*; @@ -199,7 +215,6 @@ use middle::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace, VecPerParamSpace} use middle::ty::{self, Ty}; use std::fmt; use std::rc::Rc; -use std::iter::repeat; use syntax::ast; use syntax::ast_map; use syntax::ast_util; @@ -258,6 +273,11 @@ struct TermsContext<'a, 'tcx: 'a> { empty_variances: Rc, + // For marker types, UnsafeCell, and other lang items where + // variance is hardcoded, records the item-id and the hardcoded + // variance. + lang_items: Vec<(ast::NodeId, Vec)>, + // Maps from the node id of a type/generic parameter to the // corresponding inferred index. inferred_map: NodeMap, @@ -269,7 +289,7 @@ struct TermsContext<'a, 'tcx: 'a> { #[derive(Copy, Debug, PartialEq)] enum ParamKind { TypeParam, - RegionParam + RegionParam, } struct InferredInfo<'a> { @@ -279,6 +299,11 @@ struct InferredInfo<'a> { index: uint, param_id: ast::NodeId, term: VarianceTermPtr<'a>, + + // Initial value to use for this parameter when inferring + // variance. For most parameters, this is Bivariant. But for lang + // items and input type parameters on traits, it is different. + initial_variance: ty::Variance, } fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>, @@ -291,6 +316,8 @@ fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>, inferred_map: NodeMap(), inferred_infos: Vec::new(), + lang_items: lang_items(tcx), + // cache and share the variance struct used for items with // no type/region parameters empty_variances: Rc::new(ty::ItemVariances { @@ -304,7 +331,78 @@ fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>, terms_cx } +fn lang_items(tcx: &ty::ctxt) -> Vec<(ast::NodeId,Vec)> { + let all = vec![ + (tcx.lang_items.phantom_fn(), vec![ty::Contravariant, ty::Covariant]), + (tcx.lang_items.phantom_data(), vec![ty::Covariant]), + (tcx.lang_items.unsafe_cell_type(), vec![ty::Invariant]), + + // Deprecated: + (tcx.lang_items.covariant_type(), vec![ty::Covariant]), + (tcx.lang_items.contravariant_type(), vec![ty::Contravariant]), + (tcx.lang_items.invariant_type(), vec![ty::Invariant]), + (tcx.lang_items.covariant_lifetime(), vec![ty::Covariant]), + (tcx.lang_items.contravariant_lifetime(), vec![ty::Contravariant]), + (tcx.lang_items.invariant_lifetime(), vec![ty::Invariant]), + + ]; + + all.into_iter() + .filter(|&(ref d,_)| d.is_some()) + .filter(|&(ref d,_)| d.as_ref().unwrap().krate == ast::LOCAL_CRATE) + .map(|(d, v)| (d.unwrap().node, v)) + .collect() +} + impl<'a, 'tcx> TermsContext<'a, 'tcx> { + fn add_inferreds_for_item(&mut self, + item_id: ast::NodeId, + has_self: bool, + generics: &ast::Generics) + { + /*! + * Add "inferreds" for the generic parameters declared on this + * item. This has a lot of annoying parameters because we are + * trying to drive this from the AST, rather than the + * ty::Generics, so that we can get span info -- but this + * means we must accommodate syntactic distinctions. + */ + + // NB: In the code below for writing the results back into the + // tcx, we rely on the fact that all inferreds for a particular + // item are assigned continuous indices. + + let inferreds_on_entry = self.num_inferred(); + + if has_self { + self.add_inferred(item_id, TypeParam, SelfSpace, 0, item_id); + } + + for (i, p) in generics.lifetimes.iter().enumerate() { + let id = p.lifetime.id; + self.add_inferred(item_id, RegionParam, TypeSpace, i, id); + } + + for (i, p) in generics.ty_params.iter().enumerate() { + self.add_inferred(item_id, TypeParam, TypeSpace, i, p.id); + } + + // If this item has no type or lifetime parameters, + // then there are no variances to infer, so just + // insert an empty entry into the variance map. + // Arguably we could just leave the map empty in this + // case but it seems cleaner to be able to distinguish + // "invalid item id" from "item id with no + // parameters". + if self.num_inferred() == inferreds_on_entry { + let newly_added = + self.tcx.item_variance_map.borrow_mut().insert( + ast_util::local_def(item_id), + self.empty_variances.clone()).is_none(); + assert!(newly_added); + } + } + fn add_inferred(&mut self, item_id: ast::NodeId, kind: ParamKind, @@ -313,21 +411,48 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { param_id: ast::NodeId) { let inf_index = InferredIndex(self.inferred_infos.len()); let term = self.arena.alloc(InferredTerm(inf_index)); + let initial_variance = self.pick_initial_variance(item_id, space, index); self.inferred_infos.push(InferredInfo { item_id: item_id, kind: kind, space: space, index: index, param_id: param_id, - term: term }); + term: term, + initial_variance: initial_variance }); let newly_added = self.inferred_map.insert(param_id, inf_index).is_none(); assert!(newly_added); - debug!("add_inferred(item_id={}, \ + debug!("add_inferred(item_path={}, \ + item_id={}, \ kind={:?}, \ + space={:?}, \ index={}, \ - param_id={}, - inf_index={:?})", - item_id, kind, index, param_id, inf_index); + param_id={}, \ + inf_index={:?}, \ + initial_variance={:?})", + ty::item_path_str(self.tcx, ast_util::local_def(item_id)), + item_id, kind, space, index, param_id, inf_index, + initial_variance); + } + + fn pick_initial_variance(&self, + item_id: ast::NodeId, + space: ParamSpace, + index: uint) + -> ty::Variance + { + match space { + SelfSpace | FnSpace => { + ty::Bivariant + } + + TypeSpace => { + match self.lang_items.iter().find(|&&(n, _)| n == item_id) { + Some(&(_, ref variances)) => variances[index], + None => ty::Bivariant + } + } + } } fn num_inferred(&self) -> uint { @@ -339,44 +464,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> { fn visit_item(&mut self, item: &ast::Item) { debug!("add_inferreds for item {}", item.repr(self.tcx)); - let inferreds_on_entry = self.num_inferred(); - - // NB: In the code below for writing the results back into the - // tcx, we rely on the fact that all inferreds for a particular - // item are assigned continuous indices. - match item.node { - ast::ItemTrait(..) => { - self.add_inferred(item.id, TypeParam, SelfSpace, 0, item.id); - } - _ => { } - } - match item.node { ast::ItemEnum(_, ref generics) | - ast::ItemStruct(_, ref generics) | + ast::ItemStruct(_, ref generics) => { + self.add_inferreds_for_item(item.id, false, generics); + } ast::ItemTrait(_, ref generics, _, _) => { - for (i, p) in generics.lifetimes.iter().enumerate() { - let id = p.lifetime.id; - self.add_inferred(item.id, RegionParam, TypeSpace, i, id); - } - for (i, p) in generics.ty_params.iter().enumerate() { - self.add_inferred(item.id, TypeParam, TypeSpace, i, p.id); - } - - // If this item has no type or lifetime parameters, - // then there are no variances to infer, so just - // insert an empty entry into the variance map. - // Arguably we could just leave the map empty in this - // case but it seems cleaner to be able to distinguish - // "invalid item id" from "item id with no - // parameters". - if self.num_inferred() == inferreds_on_entry { - let newly_added = self.tcx.item_variance_map.borrow_mut().insert( - ast_util::local_def(item.id), - self.empty_variances.clone()).is_none(); - assert!(newly_added); - } - + self.add_inferreds_for_item(item.id, true, generics); visit::walk_item(self, item); } @@ -404,16 +498,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> { struct ConstraintContext<'a, 'tcx: 'a> { terms_cx: TermsContext<'a, 'tcx>, - // These are the def-id of the std::marker::InvariantType, - // std::marker::InvariantLifetime, and so on. The arrays - // are indexed by the `ParamKind` (type, lifetime, self). Note - // that there are no marker types for self, so the entries for - // self are always None. - invariant_lang_items: [Option; 2], - covariant_lang_items: [Option; 2], - contravariant_lang_items: [Option; 2], - unsafe_cell_lang_item: Option, - // These are pointers to common `ConstantTerm` instances covariant: VarianceTermPtr<'a>, contravariant: VarianceTermPtr<'a>, @@ -433,40 +517,14 @@ struct Constraint<'a> { fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>, krate: &ast::Crate) - -> ConstraintContext<'a, 'tcx> { - let mut invariant_lang_items = [None; 2]; - let mut covariant_lang_items = [None; 2]; - let mut contravariant_lang_items = [None; 2]; - - covariant_lang_items[TypeParam as uint] = - terms_cx.tcx.lang_items.covariant_type(); - covariant_lang_items[RegionParam as uint] = - terms_cx.tcx.lang_items.covariant_lifetime(); - - contravariant_lang_items[TypeParam as uint] = - terms_cx.tcx.lang_items.contravariant_type(); - contravariant_lang_items[RegionParam as uint] = - terms_cx.tcx.lang_items.contravariant_lifetime(); - - invariant_lang_items[TypeParam as uint] = - terms_cx.tcx.lang_items.invariant_type(); - invariant_lang_items[RegionParam as uint] = - terms_cx.tcx.lang_items.invariant_lifetime(); - - let unsafe_cell_lang_item = terms_cx.tcx.lang_items.unsafe_cell_type(); - + -> ConstraintContext<'a, 'tcx> +{ let covariant = terms_cx.arena.alloc(ConstantTerm(ty::Covariant)); let contravariant = terms_cx.arena.alloc(ConstantTerm(ty::Contravariant)); let invariant = terms_cx.arena.alloc(ConstantTerm(ty::Invariant)); let bivariant = terms_cx.arena.alloc(ConstantTerm(ty::Bivariant)); let mut constraint_cx = ConstraintContext { terms_cx: terms_cx, - - invariant_lang_items: invariant_lang_items, - covariant_lang_items: covariant_lang_items, - contravariant_lang_items: contravariant_lang_items, - unsafe_cell_lang_item: unsafe_cell_lang_item, - covariant: covariant, contravariant: contravariant, invariant: invariant, @@ -487,7 +545,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> { match item.node { ast::ItemEnum(ref enum_definition, _) => { - let generics = &ty::lookup_item_type(tcx, did).generics; + let scheme = ty::lookup_item_type(tcx, did); + + // Not entirely obvious: constraints on structs/enums do not + // affect the variance of their type parameters. See discussion + // in comment at top of module. + // + // self.add_constraints_from_generics(&scheme.generics); // Hack: If we directly call `ty::enum_variants`, it // annoyingly takes it upon itself to run off and @@ -505,29 +569,48 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> { &**ast_variant, /*discriminant*/ 0); for arg_ty in &variant.args { - self.add_constraints_from_ty(generics, *arg_ty, self.covariant); + self.add_constraints_from_ty(&scheme.generics, *arg_ty, self.covariant); } } } ast::ItemStruct(..) => { - let generics = &ty::lookup_item_type(tcx, did).generics; + let scheme = ty::lookup_item_type(tcx, did); + + // Not entirely obvious: constraints on structs/enums do not + // affect the variance of their type parameters. See discussion + // in comment at top of module. + // + // self.add_constraints_from_generics(&scheme.generics); + let struct_fields = ty::lookup_struct_fields(tcx, did); for field_info in &struct_fields { assert_eq!(field_info.id.krate, ast::LOCAL_CRATE); let field_ty = ty::node_id_to_type(tcx, field_info.id.node); - self.add_constraints_from_ty(generics, field_ty, self.covariant); + self.add_constraints_from_ty(&scheme.generics, field_ty, self.covariant); } } ast::ItemTrait(..) => { + let trait_def = ty::lookup_trait_def(tcx, did); + let predicates = ty::predicates(tcx, ty::mk_self_type(tcx), &trait_def.bounds); + self.add_constraints_from_predicates(&trait_def.generics, + &predicates[], + self.covariant); + let trait_items = ty::trait_items(tcx, did); for trait_item in &*trait_items { match *trait_item { ty::MethodTraitItem(ref method) => { - self.add_constraints_from_sig(&method.generics, - &method.fty.sig, - self.covariant); + self.add_constraints_from_predicates( + &method.generics, + method.predicates.predicates.get_slice(FnSpace), + self.contravariant); + + self.add_constraints_from_sig( + &method.generics, + &method.fty.sig, + self.covariant); } ty::TypeTraitItem(_) => {} } @@ -544,9 +627,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> { ast::ItemTy(..) | ast::ItemImpl(..) | ast::ItemMac(..) => { - visit::walk_item(self, item); } } + + visit::walk_item(self, item); } } @@ -648,15 +732,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { -> VarianceTermPtr<'a> { assert_eq!(param_def_id.krate, item_def_id.krate); - if self.invariant_lang_items[kind as uint] == Some(item_def_id) { - self.invariant - } else if self.covariant_lang_items[kind as uint] == Some(item_def_id) { - self.covariant - } else if self.contravariant_lang_items[kind as uint] == Some(item_def_id) { - self.contravariant - } else if kind == TypeParam && Some(item_def_id) == self.unsafe_cell_lang_item { - self.invariant - } else if param_def_id.krate == ast::LOCAL_CRATE { + if param_def_id.krate == ast::LOCAL_CRATE { // Parameter on an item defined within current crate: // variance not yet inferred, so return a symbolic // variance. @@ -724,6 +800,25 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } } + fn add_constraints_from_trait_ref(&mut self, + generics: &ty::Generics<'tcx>, + trait_ref: &ty::TraitRef<'tcx>, + variance: VarianceTermPtr<'a>) { + debug!("add_constraints_from_trait_ref: trait_ref={} variance={:?}", + trait_ref.repr(self.tcx()), + variance); + + let trait_def = ty::lookup_trait_def(self.tcx(), trait_ref.def_id); + + self.add_constraints_from_substs( + generics, + trait_ref.def_id, + trait_def.generics.types.as_slice(), + trait_def.generics.regions.as_slice(), + trait_ref.substs, + variance); + } + /// Adds constraints appropriate for an instance of `ty` appearing /// in a context with the generics defined in `generics` and /// ambient variance `variance` @@ -731,7 +826,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { generics: &ty::Generics<'tcx>, ty: Ty<'tcx>, variance: VarianceTermPtr<'a>) { - debug!("add_constraints_from_ty(ty={})", ty.repr(self.tcx())); + debug!("add_constraints_from_ty(ty={}, variance={:?})", + ty.repr(self.tcx()), + variance); match ty.sty { ty::ty_bool | @@ -754,6 +851,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_ty(generics, typ, variance); } + ty::ty_ptr(ref mt) => { self.add_constraints_from_mt(generics, mt, variance); } @@ -797,27 +895,16 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::ty_trait(ref data) => { - let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(), - self.tcx().types.err); - let trait_def = ty::lookup_trait_def(self.tcx(), trait_ref.def_id()); - - // Traits never declare region parameters in the self - // space nor anything in the fn space. - assert!(trait_def.generics.regions.is_empty_in(subst::SelfSpace)); - assert!(trait_def.generics.types.is_empty_in(subst::FnSpace)); - assert!(trait_def.generics.regions.is_empty_in(subst::FnSpace)); + let poly_trait_ref = + data.principal_trait_ref_with_self_ty(self.tcx(), + self.tcx().types.err); // The type `Foo` is contravariant w/r/t `'a`: let contra = self.contravariant(variance); self.add_constraints_from_region(generics, data.bounds.region_bound, contra); - self.add_constraints_from_substs( - generics, - trait_ref.def_id(), - trait_def.generics.types.get_slice(subst::TypeSpace), - trait_def.generics.regions.get_slice(subst::TypeSpace), - trait_ref.substs(), - variance); + // Ignore the SelfSpace, it is erased. + self.add_constraints_from_trait_ref(generics, &*poly_trait_ref.0, variance); let projections = data.projection_bounds_with_self_ty(self.tcx(), self.tcx().types.err); @@ -845,7 +932,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_sig(generics, sig, variance); } - ty::ty_infer(..) | ty::ty_err => { + ty::ty_err => { + // we encounter this when walking the trait references for object + // types, where we use ty_err as the Self type + } + + ty::ty_infer(..) => { self.tcx().sess.bug( &format!("unexpected type encountered in \ variance inference: {}", @@ -864,7 +956,10 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { region_param_defs: &[ty::RegionParameterDef], substs: &subst::Substs<'tcx>, variance: VarianceTermPtr<'a>) { - debug!("add_constraints_from_substs(def_id={:?})", def_id); + debug!("add_constraints_from_substs(def_id={}, substs={}, variance={:?})", + def_id.repr(self.tcx()), + substs.repr(self.tcx()), + variance); for p in type_param_defs { let variance_decl = @@ -872,6 +967,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { p.space, p.index as uint); let variance_i = self.xform(variance, variance_decl); let substs_ty = *substs.types.get(p.space, p.index as uint); + debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}", + variance_decl, variance_i); self.add_constraints_from_ty(generics, substs_ty, variance_i); } @@ -885,6 +982,51 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } } + fn add_constraints_from_predicates(&mut self, + generics: &ty::Generics<'tcx>, + predicates: &[ty::Predicate<'tcx>], + variance: VarianceTermPtr<'a>) { + debug!("add_constraints_from_generics({})", + generics.repr(self.tcx())); + + for predicate in predicates.iter() { + match *predicate { + ty::Predicate::Trait(ty::Binder(ref data)) => { + self.add_constraints_from_trait_ref(generics, &*data.trait_ref, variance); + } + + ty::Predicate::Equate(ty::Binder(ref data)) => { + self.add_constraints_from_ty(generics, data.0, variance); + self.add_constraints_from_ty(generics, data.1, variance); + } + + ty::Predicate::TypeOutlives(ty::Binder(ref data)) => { + self.add_constraints_from_ty(generics, data.0, variance); + + let variance_r = self.xform(variance, self.contravariant); + self.add_constraints_from_region(generics, data.1, variance_r); + } + + ty::Predicate::RegionOutlives(ty::Binder(ref data)) => { + // `'a : 'b` is still true if 'a gets bigger + self.add_constraints_from_region(generics, data.0, variance); + + // `'a : 'b` is still true if 'b gets smaller + let variance_r = self.xform(variance, self.contravariant); + self.add_constraints_from_region(generics, data.1, variance_r); + } + + ty::Predicate::Projection(ty::Binder(ref data)) => { + self.add_constraints_from_trait_ref(generics, + &*data.projection_ty.trait_ref, + variance); + + self.add_constraints_from_ty(generics, data.ty, self.invariant); + } + } + } + } + /// Adds constraints appropriate for a function with signature /// `sig` appearing in a context with ambient variance `variance` fn add_constraints_from_sig(&mut self, @@ -969,7 +1111,12 @@ struct SolveContext<'a, 'tcx: 'a> { fn solve_constraints(constraints_cx: ConstraintContext) { let ConstraintContext { terms_cx, constraints, .. } = constraints_cx; - let solutions: Vec<_> = repeat(ty::Bivariant).take(terms_cx.num_inferred()).collect(); + + let solutions = + terms_cx.inferred_infos.iter() + .map(|ii| ii.initial_variance) + .collect(); + let mut solutions_cx = SolveContext { terms_cx: terms_cx, constraints: constraints, @@ -1034,20 +1181,16 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { let mut types = VecPerParamSpace::empty(); let mut regions = VecPerParamSpace::empty(); - while index < num_inferred && - inferred_infos[index].item_id == item_id { + while index < num_inferred && inferred_infos[index].item_id == item_id { let info = &inferred_infos[index]; let variance = solutions[index]; debug!("Index {} Info {} / {:?} / {:?} Variance {:?}", index, info.index, info.kind, info.space, variance); match info.kind { - TypeParam => { - types.push(info.space, variance); - } - RegionParam => { - regions.push(info.space, variance); - } + TypeParam => { types.push(info.space, variance); } + RegionParam => { regions.push(info.space, variance); } } + index += 1; } @@ -1144,3 +1287,4 @@ fn glb(v1: ty::Variance, v2: ty::Variance) -> ty::Variance { (x, ty::Bivariant) | (ty::Bivariant, x) => x, } } + diff --git a/src/libstd/collections/hash/state.rs b/src/libstd/collections/hash/state.rs index 79e01304fb8..7e6dd45b51e 100644 --- a/src/libstd/collections/hash/state.rs +++ b/src/libstd/collections/hash/state.rs @@ -11,6 +11,7 @@ use clone::Clone; use default::Default; use hash; +use marker; /// A trait representing stateful hashes which can be used to hash keys in a /// `HashMap`. @@ -37,7 +38,7 @@ pub trait HashState { /// /// This struct has is 0-sized and does not need construction. #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")] -pub struct DefaultState; +pub struct DefaultState(marker::PhantomData); impl HashState for DefaultState { type Hasher = H; @@ -45,9 +46,9 @@ impl HashState for DefaultState { } impl Clone for DefaultState { - fn clone(&self) -> DefaultState { DefaultState } + fn clone(&self) -> DefaultState { DefaultState(marker::PhantomData) } } impl Default for DefaultState { - fn default() -> DefaultState { DefaultState } + fn default() -> DefaultState { DefaultState(marker::PhantomData) } } diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 7114da93ea0..f301f6db92f 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -23,8 +23,8 @@ use num::{Int, UnsignedInt}; use ops::{Deref, DerefMut, Drop}; use option::Option; use option::Option::{Some, None}; -use ptr::{self, PtrExt, copy_nonoverlapping_memory, zero_memory}; -use rt::heap::{allocate, deallocate}; +use ptr::{self, PtrExt, copy_nonoverlapping_memory, Unique, zero_memory}; +use rt::heap::{allocate, deallocate, EMPTY}; use collections::hash_state::HashState; const EMPTY_BUCKET: u64 = 0u64; @@ -69,10 +69,11 @@ const EMPTY_BUCKET: u64 = 0u64; pub struct RawTable { capacity: usize, size: usize, - hashes: *mut u64, + hashes: Unique, + // Because K/V do not appear directly in any of the types in the struct, // inform rustc that in fact instances of K and V are reachable from here. - marker: marker::CovariantType<(K,V)>, + marker: marker::PhantomData<(K,V)>, } unsafe impl Send for RawTable {} @@ -81,7 +82,8 @@ unsafe impl Sync for RawTable {} struct RawBucket { hash: *mut u64, key: *mut K, - val: *mut V + val: *mut V, + _marker: marker::PhantomData<(K,V)>, } impl Copy for RawBucket {} @@ -187,11 +189,12 @@ fn can_alias_safehash_as_u64() { } impl RawBucket { - unsafe fn offset(self, count: int) -> RawBucket { + unsafe fn offset(self, count: isize) -> RawBucket { RawBucket { hash: self.hash.offset(count), key: self.key.offset(count), val: self.val.offset(count), + _marker: marker::PhantomData, } } } @@ -584,10 +587,11 @@ impl RawTable { return RawTable { size: 0, capacity: 0, - hashes: ptr::null_mut(), - marker: marker::CovariantType, + hashes: Unique::new(EMPTY as *mut u64), + marker: marker::PhantomData, }; } + // No need for `checked_mul` before a more restrictive check performed // later in this method. let hashes_size = capacity * size_of::(); @@ -623,8 +627,8 @@ impl RawTable { RawTable { capacity: capacity, size: 0, - hashes: hashes, - marker: marker::CovariantType, + hashes: Unique::new(hashes), + marker: marker::PhantomData, } } @@ -632,16 +636,17 @@ impl RawTable { let hashes_size = self.capacity * size_of::(); let keys_size = self.capacity * size_of::(); - let buffer = self.hashes as *mut u8; + let buffer = *self.hashes as *mut u8; let (keys_offset, vals_offset) = calculate_offsets(hashes_size, keys_size, min_align_of::(), min_align_of::()); unsafe { RawBucket { - hash: self.hashes, + hash: *self.hashes, key: buffer.offset(keys_offset as isize) as *mut K, - val: buffer.offset(vals_offset as isize) as *mut V + val: buffer.offset(vals_offset as isize) as *mut V, + _marker: marker::PhantomData, } } } @@ -651,7 +656,7 @@ impl RawTable { pub fn new(capacity: usize) -> RawTable { unsafe { let ret = RawTable::new_uninitialized(capacity); - zero_memory(ret.hashes, capacity); + zero_memory(*ret.hashes, capacity); ret } } @@ -673,7 +678,7 @@ impl RawTable { hashes_end: unsafe { self.hashes.offset(self.capacity as isize) }, - marker: marker::ContravariantLifetime, + marker: marker::PhantomData, } } @@ -698,7 +703,7 @@ impl RawTable { iter: RawBuckets { raw: raw, hashes_end: hashes_end, - marker: marker::ContravariantLifetime, + marker: marker::PhantomData, }, table: self, } @@ -711,7 +716,7 @@ impl RawTable { iter: RawBuckets { raw: raw, hashes_end: hashes_end, - marker: marker::ContravariantLifetime::<'static>, + marker: marker::PhantomData, }, table: self, } @@ -725,7 +730,7 @@ impl RawTable { raw: raw_bucket.offset(self.capacity as isize), hashes_end: raw_bucket.hash, elems_left: self.size, - marker: marker::ContravariantLifetime, + marker: marker::PhantomData, } } } @@ -735,7 +740,13 @@ impl RawTable { struct RawBuckets<'a, K, V> { raw: RawBucket, hashes_end: *mut u64, - marker: marker::ContravariantLifetime<'a>, + + // Strictly speaking, this should be &'a (K,V), but that would + // require that K:'a, and we often use RawBuckets<'static...> for + // move iterations, so that messes up a lot of other things. So + // just use `&'a (K,V)` as this is not a publicly exposed type + // anyway. + marker: marker::PhantomData<&'a ()>, } // FIXME(#19839) Remove in favor of `#[derive(Clone)]` @@ -744,7 +755,7 @@ impl<'a, K, V> Clone for RawBuckets<'a, K, V> { RawBuckets { raw: self.raw, hashes_end: self.hashes_end, - marker: marker::ContravariantLifetime, + marker: marker::PhantomData, } } } @@ -776,7 +787,11 @@ struct RevMoveBuckets<'a, K, V> { raw: RawBucket, hashes_end: *mut u64, elems_left: usize, - marker: marker::ContravariantLifetime<'a>, + + // As above, `&'a (K,V)` would seem better, but we often use + // 'static for the lifetime, and this is not a publicly exposed + // type. + marker: marker::PhantomData<&'a ()>, } impl<'a, K, V> Iterator for RevMoveBuckets<'a, K, V> { @@ -983,9 +998,10 @@ impl Clone for RawTable { #[unsafe_destructor] impl Drop for RawTable { fn drop(&mut self) { - if self.hashes.is_null() { + if self.capacity == 0 { return; } + // This is done in reverse because we've likely partially taken // some elements out with `.into_iter()` from the front. // Check if the size is 0, so we don't do a useless scan when @@ -1003,7 +1019,7 @@ impl Drop for RawTable { vals_size, min_align_of::()); unsafe { - deallocate(self.hashes as *mut u8, size, align); + deallocate(*self.hashes as *mut u8, size, align); // Remember how everything was allocated out of one buffer // during initialization? We only need one call to free here. } diff --git a/src/libstd/old_io/mod.rs b/src/libstd/old_io/mod.rs index 21282a0c28a..fc3deb67f41 100644 --- a/src/libstd/old_io/mod.rs +++ b/src/libstd/old_io/mod.rs @@ -252,7 +252,7 @@ use error::Error; use fmt; use isize; use iter::{Iterator, IteratorExt}; -use marker::Sized; +use marker::{PhantomFn, Sized}; use mem::transmute; use ops::FnOnce; use option::Option; @@ -433,7 +433,7 @@ pub enum IoErrorKind { } /// A trait that lets you add a `detail` to an IoError easily -trait UpdateIoError { +trait UpdateIoError { /// Returns an IoError with updated description and detail fn update_err(self, desc: &'static str, detail: D) -> Self where D: FnOnce(&IoError) -> String; @@ -446,7 +446,7 @@ trait UpdateIoError { fn update_desc(self, desc: &'static str) -> Self; } -impl UpdateIoError for IoResult { +impl UpdateIoError for IoResult { fn update_err(self, desc: &'static str, detail: D) -> IoResult where D: FnOnce(&IoError) -> String, { @@ -1572,7 +1572,9 @@ pub trait Seek { /// connections. /// /// Doing so produces some sort of Acceptor. -pub trait Listener> { +pub trait Listener> + : PhantomFn // FIXME should be an assoc type anyhow +{ /// Spin up the listener and start queuing incoming connections /// /// # Error diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs index 3137d779c40..3653e7e31d5 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -153,7 +153,7 @@ use any::Any; use cell::UnsafeCell; use fmt; use io; -use marker; +use marker::PhantomData; use old_io::stdio; use rt::{self, unwind}; use sync::{Mutex, Condvar, Arc}; @@ -260,7 +260,7 @@ impl Builder { T: Send + 'a, F: FnOnce() -> T, F: Send + 'a { self.spawn_inner(Thunk::new(f)).map(|inner| { - JoinGuard { inner: inner, _marker: marker::CovariantType } + JoinGuard { inner: inner, _marker: PhantomData } }) } @@ -642,7 +642,7 @@ impl Drop for JoinHandle { #[stable(feature = "rust1", since = "1.0.0")] pub struct JoinGuard<'a, T: 'a> { inner: JoinInner, - _marker: marker::CovariantType<&'a T>, + _marker: PhantomData<&'a T>, } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 8c2b9edfb22..4e4a571ede7 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -45,11 +45,11 @@ fn no_prelude(attrs: &[ast::Attribute]) -> bool { attr::contains_name(attrs, "no_implicit_prelude") } -struct StandardLibraryInjector<'a> { - alt_std_name: Option +struct StandardLibraryInjector { + alt_std_name: Option, } -impl<'a> fold::Folder for StandardLibraryInjector<'a> { +impl fold::Folder for StandardLibraryInjector { fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { // The name to use in `extern crate "name" as std;` @@ -80,9 +80,10 @@ fn inject_crates_ref(krate: ast::Crate, alt_std_name: Option) -> ast::Cr fold.fold_crate(krate) } -struct PreludeInjector<'a>; +struct PreludeInjector; -impl<'a> fold::Folder for PreludeInjector<'a> { + +impl fold::Folder for PreludeInjector { fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { // only add `use std::prelude::*;` if there wasn't a // `#![no_implicit_prelude]` at the crate level. diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 304f370a199..5418533aff1 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -50,7 +50,6 @@ html_playground_url = "http://play.rust-lang.org/")] #![deny(missing_docs)] -#![feature(core)] #![feature(box_syntax)] #![feature(collections)] #![feature(int_uint)] diff --git a/src/test/auxiliary/coherence-orphan-lib.rs b/src/test/auxiliary/coherence-orphan-lib.rs index 2e5d18b58f2..cc42b288e66 100644 --- a/src/test/auxiliary/coherence-orphan-lib.rs +++ b/src/test/auxiliary/coherence-orphan-lib.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub trait TheTrait { +pub trait TheTrait : ::std::marker::PhantomFn { fn the_fn(&self); } diff --git a/src/test/auxiliary/default_type_params_xc.rs b/src/test/auxiliary/default_type_params_xc.rs index d12f716decf..0a65174911e 100644 --- a/src/test/auxiliary/default_type_params_xc.rs +++ b/src/test/auxiliary/default_type_params_xc.rs @@ -12,4 +12,5 @@ pub struct Heap; pub struct FakeHeap; -pub struct FakeVec; +pub struct FakeVec { pub f: Option<(T,A)> } + diff --git a/src/test/auxiliary/inner_static.rs b/src/test/auxiliary/inner_static.rs index 94acea06618..ca5c6072cb3 100644 --- a/src/test/auxiliary/inner_static.rs +++ b/src/test/auxiliary/inner_static.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub struct A; -pub struct B; +pub struct A { pub v: T } +pub struct B { pub v: T } pub mod test { - pub struct A; + pub struct A { pub v: T } impl A { pub fn foo(&self) -> int { @@ -52,9 +52,9 @@ impl B { } pub fn foo() -> int { - let a = A::<()>; - let b = B::<()>; - let c = test::A::<()>; + let a = A { v: () }; + let b = B { v: () }; + let c = test::A { v: () }; return a.foo() + a.bar() + b.foo() + b.bar() + c.foo() + c.bar(); diff --git a/src/test/auxiliary/issue-14421.rs b/src/test/auxiliary/issue-14421.rs index 7c69cba179c..a48088609f9 100644 --- a/src/test/auxiliary/issue-14421.rs +++ b/src/test/auxiliary/issue-14421.rs @@ -10,6 +10,7 @@ #![crate_type="lib"] #![deny(warnings)] +#![allow(dead_code)] pub use src::aliases::B; pub use src::hidden_core::make; @@ -23,9 +24,9 @@ mod src { pub mod hidden_core { use super::aliases::B; - pub struct A; + pub struct A { t: T } - pub fn make() -> B { A } + pub fn make() -> B { A { t: 1.0 } } impl A { pub fn foo(&mut self) { println!("called foo"); } diff --git a/src/test/auxiliary/issue-16643.rs b/src/test/auxiliary/issue-16643.rs index c5b3fceaf4a..b590160a0c2 100644 --- a/src/test/auxiliary/issue-16643.rs +++ b/src/test/auxiliary/issue-16643.rs @@ -10,7 +10,7 @@ #![crate_type = "lib"] -pub struct TreeBuilder; +pub struct TreeBuilder { pub h: H } impl TreeBuilder { pub fn process_token(&mut self) { diff --git a/src/test/auxiliary/issue-17662.rs b/src/test/auxiliary/issue-17662.rs index be10ca1dd8f..fb55a077005 100644 --- a/src/test/auxiliary/issue-17662.rs +++ b/src/test/auxiliary/issue-17662.rs @@ -11,7 +11,7 @@ #![crate_type = "lib"] pub trait Foo<'a, T> { - fn foo(&self) -> T; + fn foo(&'a self) -> T; } pub fn foo<'a, T>(x: &'a Foo<'a, T>) -> T { diff --git a/src/test/auxiliary/issue-2380.rs b/src/test/auxiliary/issue-2380.rs index 8eb6cd6e263..96f33f97a69 100644 --- a/src/test/auxiliary/issue-2380.rs +++ b/src/test/auxiliary/issue-2380.rs @@ -14,7 +14,10 @@ #![allow(unknown_features)] #![feature(box_syntax)] -pub trait i { } +pub trait i +{ + fn dummy(&self, t: T) -> T { panic!() } +} pub fn f() -> Box+'static> { impl i for () { } diff --git a/src/test/auxiliary/issue-2526.rs b/src/test/auxiliary/issue-2526.rs index e3ce4e8f656..89b3b56121a 100644 --- a/src/test/auxiliary/issue-2526.rs +++ b/src/test/auxiliary/issue-2526.rs @@ -13,8 +13,11 @@ #![feature(unsafe_destructor)] +use std::marker; + struct arc_destruct { - _data: int, + _data: int, + _marker: marker::PhantomData } #[unsafe_destructor] @@ -24,7 +27,8 @@ impl Drop for arc_destruct { fn arc_destruct(data: int) -> arc_destruct { arc_destruct { - _data: data + _data: data, + _marker: marker::PhantomData } } diff --git a/src/test/auxiliary/issue_20389.rs b/src/test/auxiliary/issue_20389.rs index 7a378b06df9..4ce7e3079e3 100644 --- a/src/test/auxiliary/issue_20389.rs +++ b/src/test/auxiliary/issue_20389.rs @@ -10,4 +10,5 @@ pub trait T { type C; + fn dummy(&self) { } } diff --git a/src/test/auxiliary/issue_3907.rs b/src/test/auxiliary/issue_3907.rs index 2e254e5431d..545e15fe166 100644 --- a/src/test/auxiliary/issue_3907.rs +++ b/src/test/auxiliary/issue_3907.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub trait Foo { +use std::marker::MarkerTrait; + +pub trait Foo : MarkerTrait { fn bar(); } diff --git a/src/test/auxiliary/issue_8401.rs b/src/test/auxiliary/issue_8401.rs index 0831993119a..9006a5d1775 100644 --- a/src/test/auxiliary/issue_8401.rs +++ b/src/test/auxiliary/issue_8401.rs @@ -12,7 +12,9 @@ use std::mem; -trait A {} +trait A { + fn dummy(&self) { } +} struct B; impl A for B {} diff --git a/src/test/auxiliary/issue_9123.rs b/src/test/auxiliary/issue_9123.rs index 000cc100a12..4f2792aebcd 100644 --- a/src/test/auxiliary/issue_9123.rs +++ b/src/test/auxiliary/issue_9123.rs @@ -15,5 +15,6 @@ pub trait X { fn f() { } f(); } + fn dummy(&self) { } } diff --git a/src/test/auxiliary/lang-item-public.rs b/src/test/auxiliary/lang-item-public.rs index 834667968c8..b9cc20b63cc 100644 --- a/src/test/auxiliary/lang-item-public.rs +++ b/src/test/auxiliary/lang-item-public.rs @@ -12,8 +12,12 @@ #![no_std] #![feature(lang_items)] +#[lang="phantom_fn"] +pub trait PhantomFn { } +impl PhantomFn for U { } + #[lang="sized"] -pub trait Sized {} +pub trait Sized : PhantomFn {} #[lang="panic"] fn panic(_: &(&'static str, &'static str, uint)) -> ! { loop {} } @@ -25,6 +29,8 @@ extern fn stack_exhausted() {} extern fn eh_personality() {} #[lang="copy"] -pub trait Copy {} +pub trait Copy : PhantomFn { + // Empty. +} diff --git a/src/test/auxiliary/lint_stability.rs b/src/test/auxiliary/lint_stability.rs index 01b2b748ba9..fb535eb8336 100644 --- a/src/test/auxiliary/lint_stability.rs +++ b/src/test/auxiliary/lint_stability.rs @@ -96,7 +96,7 @@ pub trait Trait { impl Trait for MethodTester {} #[unstable(feature = "test_feature")] -pub trait UnstableTrait {} +pub trait UnstableTrait { fn dummy(&self) { } } #[stable(feature = "test_feature", since = "1.0.0")] #[deprecated(since = "1.0.0")] diff --git a/src/test/auxiliary/nested_item.rs b/src/test/auxiliary/nested_item.rs index 21784bda27a..fc1bea5a9fd 100644 --- a/src/test/auxiliary/nested_item.rs +++ b/src/test/auxiliary/nested_item.rs @@ -25,7 +25,7 @@ impl Foo { } // issue 8134 -pub struct Parser; +pub struct Parser(T); impl> Parser { fn in_doctype(&mut self) { static DOCTYPEPattern: [char; 6] = ['O', 'C', 'T', 'Y', 'P', 'E']; diff --git a/src/test/auxiliary/orphan_check_diagnostics.rs b/src/test/auxiliary/orphan_check_diagnostics.rs index 7647f159401..cf3e9903b5a 100644 --- a/src/test/auxiliary/orphan_check_diagnostics.rs +++ b/src/test/auxiliary/orphan_check_diagnostics.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub trait RemoteTrait {} +pub trait RemoteTrait { fn dummy(&self) { } } diff --git a/src/test/auxiliary/overloaded_autoderef_xc.rs b/src/test/auxiliary/overloaded_autoderef_xc.rs index caa9bbe5736..3c8cba13ae7 100644 --- a/src/test/auxiliary/overloaded_autoderef_xc.rs +++ b/src/test/auxiliary/overloaded_autoderef_xc.rs @@ -11,7 +11,8 @@ use std::ops::Deref; struct DerefWithHelper { - pub helper: H + pub helper: H, + pub value: Option } trait Helper { @@ -34,6 +35,6 @@ impl> Deref for DerefWithHelper { // Test cross-crate autoderef + vtable. pub fn check(x: T, y: T) -> bool { - let d: DerefWithHelper, T> = DerefWithHelper { helper: Some(x) }; + let d: DerefWithHelper, T> = DerefWithHelper { helper: Some(x), value: None }; d.eq(&y) } diff --git a/src/test/auxiliary/private_trait_xc.rs b/src/test/auxiliary/private_trait_xc.rs index 37ee10c8d37..42691579491 100644 --- a/src/test/auxiliary/private_trait_xc.rs +++ b/src/test/auxiliary/private_trait_xc.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo {} +trait Foo : ::std::marker::MarkerTrait {} diff --git a/src/test/auxiliary/svh-a-base.rs b/src/test/auxiliary/svh-a-base.rs index 12833daf604..04f1062c16f 100644 --- a/src/test/auxiliary/svh-a-base.rs +++ b/src/test/auxiliary/svh-a-base.rs @@ -15,12 +15,14 @@ #![crate_name = "a"] +use std::marker::MarkerTrait; + macro_rules! three { () => { 3 } } -pub trait U {} -pub trait V {} +pub trait U : MarkerTrait {} +pub trait V : MarkerTrait {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-change-lit.rs b/src/test/auxiliary/svh-a-change-lit.rs index 9e74bf28135..fabd2289e9a 100644 --- a/src/test/auxiliary/svh-a-change-lit.rs +++ b/src/test/auxiliary/svh-a-change-lit.rs @@ -15,12 +15,14 @@ #![crate_name = "a"] +use std::marker::MarkerTrait; + macro_rules! three { () => { 3 } } -pub trait U {} -pub trait V {} +pub trait U : MarkerTrait {} +pub trait V : MarkerTrait {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-change-significant-cfg.rs b/src/test/auxiliary/svh-a-change-significant-cfg.rs index c900550041b..3fdb861bd40 100644 --- a/src/test/auxiliary/svh-a-change-significant-cfg.rs +++ b/src/test/auxiliary/svh-a-change-significant-cfg.rs @@ -15,12 +15,14 @@ #![crate_name = "a"] +use std::marker::MarkerTrait; + macro_rules! three { () => { 3 } } -pub trait U {} -pub trait V {} +pub trait U : MarkerTrait {} +pub trait V : MarkerTrait {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-change-trait-bound.rs b/src/test/auxiliary/svh-a-change-trait-bound.rs index 04f8eb3cf9b..3116d24673d 100644 --- a/src/test/auxiliary/svh-a-change-trait-bound.rs +++ b/src/test/auxiliary/svh-a-change-trait-bound.rs @@ -15,12 +15,14 @@ #![crate_name = "a"] +use std::marker::MarkerTrait; + macro_rules! three { () => { 3 } } -pub trait U {} -pub trait V {} +pub trait U : MarkerTrait {} +pub trait V : MarkerTrait {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-change-type-arg.rs b/src/test/auxiliary/svh-a-change-type-arg.rs index c7e0a18768a..b49a1533628 100644 --- a/src/test/auxiliary/svh-a-change-type-arg.rs +++ b/src/test/auxiliary/svh-a-change-type-arg.rs @@ -15,12 +15,14 @@ #![crate_name = "a"] +use std::marker::MarkerTrait; + macro_rules! three { () => { 3 } } -pub trait U {} -pub trait V {} +pub trait U : MarkerTrait {} +pub trait V : MarkerTrait {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-change-type-ret.rs b/src/test/auxiliary/svh-a-change-type-ret.rs index 5100af32318..6562a93135f 100644 --- a/src/test/auxiliary/svh-a-change-type-ret.rs +++ b/src/test/auxiliary/svh-a-change-type-ret.rs @@ -15,12 +15,14 @@ #![crate_name = "a"] +use std::marker::MarkerTrait; + macro_rules! three { () => { 3 } } -pub trait U {} -pub trait V {} +pub trait U : MarkerTrait {} +pub trait V : MarkerTrait {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-change-type-static.rs b/src/test/auxiliary/svh-a-change-type-static.rs index 077c33cb90d..c7b392c6ee8 100644 --- a/src/test/auxiliary/svh-a-change-type-static.rs +++ b/src/test/auxiliary/svh-a-change-type-static.rs @@ -15,12 +15,14 @@ #![crate_name = "a"] +use std::marker::MarkerTrait; + macro_rules! three { () => { 3 } } -pub trait U {} -pub trait V {} +pub trait U : MarkerTrait {} +pub trait V : MarkerTrait {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-comment.rs b/src/test/auxiliary/svh-a-comment.rs index d481fa5a1fa..450f6102026 100644 --- a/src/test/auxiliary/svh-a-comment.rs +++ b/src/test/auxiliary/svh-a-comment.rs @@ -15,12 +15,14 @@ #![crate_name = "a"] +use std::marker::MarkerTrait; + macro_rules! three { () => { 3 } } -pub trait U {} -pub trait V {} +pub trait U : MarkerTrait {} +pub trait V : MarkerTrait {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-doc.rs b/src/test/auxiliary/svh-a-doc.rs index 9e99a355ac1..c000737c854 100644 --- a/src/test/auxiliary/svh-a-doc.rs +++ b/src/test/auxiliary/svh-a-doc.rs @@ -15,12 +15,14 @@ #![crate_name = "a"] +use std::marker::MarkerTrait; + macro_rules! three { () => { 3 } } -pub trait U {} -pub trait V {} +pub trait U : MarkerTrait {} +pub trait V : MarkerTrait {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-macro.rs b/src/test/auxiliary/svh-a-macro.rs index b8dd497ac99..1e12659dc4b 100644 --- a/src/test/auxiliary/svh-a-macro.rs +++ b/src/test/auxiliary/svh-a-macro.rs @@ -15,12 +15,14 @@ #![crate_name = "a"] +use std::marker::MarkerTrait; + macro_rules! three { () => { 3 } } -pub trait U {} -pub trait V {} +pub trait U : MarkerTrait {} +pub trait V : MarkerTrait {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-no-change.rs b/src/test/auxiliary/svh-a-no-change.rs index 12833daf604..04f1062c16f 100644 --- a/src/test/auxiliary/svh-a-no-change.rs +++ b/src/test/auxiliary/svh-a-no-change.rs @@ -15,12 +15,14 @@ #![crate_name = "a"] +use std::marker::MarkerTrait; + macro_rules! three { () => { 3 } } -pub trait U {} -pub trait V {} +pub trait U : MarkerTrait {} +pub trait V : MarkerTrait {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-redundant-cfg.rs b/src/test/auxiliary/svh-a-redundant-cfg.rs index 690ddc670f5..1e82b74f1ef 100644 --- a/src/test/auxiliary/svh-a-redundant-cfg.rs +++ b/src/test/auxiliary/svh-a-redundant-cfg.rs @@ -15,12 +15,14 @@ #![crate_name = "a"] +use std::marker::MarkerTrait; + macro_rules! three { () => { 3 } } -pub trait U {} -pub trait V {} +pub trait U : MarkerTrait {} +pub trait V : MarkerTrait {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-whitespace.rs b/src/test/auxiliary/svh-a-whitespace.rs index 216e8e997f2..3c3dac9cdab 100644 --- a/src/test/auxiliary/svh-a-whitespace.rs +++ b/src/test/auxiliary/svh-a-whitespace.rs @@ -15,12 +15,14 @@ #![crate_name = "a"] +use std::marker::MarkerTrait; + macro_rules! three { () => { 3 } } -pub trait U {} -pub trait V {} +pub trait U : MarkerTrait {} +pub trait V : MarkerTrait {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/trait_bounds_on_structs_and_enums_xc.rs b/src/test/auxiliary/trait_bounds_on_structs_and_enums_xc.rs index 1695e474de9..a7c469fccaa 100644 --- a/src/test/auxiliary/trait_bounds_on_structs_and_enums_xc.rs +++ b/src/test/auxiliary/trait_bounds_on_structs_and_enums_xc.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub trait Trait {} +pub trait Trait { + fn dummy(&self) { } +} pub struct Foo { pub x: T, diff --git a/src/test/auxiliary/trait_impl_conflict.rs b/src/test/auxiliary/trait_impl_conflict.rs index 990bc216049..0982efbdbf4 100644 --- a/src/test/auxiliary/trait_impl_conflict.rs +++ b/src/test/auxiliary/trait_impl_conflict.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub trait Foo { +pub trait Foo : ::std::marker::MarkerTrait { } impl Foo for int { diff --git a/src/test/auxiliary/use_from_trait_xc.rs b/src/test/auxiliary/use_from_trait_xc.rs index 22e0d3168ca..56fb40bc0a4 100644 --- a/src/test/auxiliary/use_from_trait_xc.rs +++ b/src/test/auxiliary/use_from_trait_xc.rs @@ -11,7 +11,7 @@ pub use self::sub::{Bar, Baz}; pub trait Trait { - fn foo(); + fn foo(&self); } struct Foo; diff --git a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs index 621f5ec9660..edd1b8255cc 100644 --- a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs +++ b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs @@ -16,8 +16,12 @@ #![feature(no_std)] #![no_std] +#[lang="phantom_fn"] +pub trait PhantomFn { } +impl PhantomFn for U { } + #[lang="sized"] -pub trait Sized { +pub trait Sized : PhantomFn { // Empty. } diff --git a/src/test/compile-fail/associated-types-coherence-failure.rs b/src/test/compile-fail/associated-types-coherence-failure.rs index 95a68dd6698..b7a16c68a34 100644 --- a/src/test/compile-fail/associated-types-coherence-failure.rs +++ b/src/test/compile-fail/associated-types-coherence-failure.rs @@ -11,9 +11,10 @@ // Test that coherence detects overlap when some of the types in the // impls are projections of associated type. Issue #20624. +use std::marker::PhantomData; use std::ops::Deref; -pub struct Cow<'a, B: ?Sized>; +pub struct Cow<'a, B: ?Sized>(PhantomData<(&'a (),B)>); /// Trait for moving into a `Cow` pub trait IntoCow<'a, B: ?Sized> { diff --git a/src/test/compile-fail/associated-types-eq-expr-path.rs b/src/test/compile-fail/associated-types-eq-expr-path.rs index 9baa7f1ad5a..c48f9972ebc 100644 --- a/src/test/compile-fail/associated-types-eq-expr-path.rs +++ b/src/test/compile-fail/associated-types-eq-expr-path.rs @@ -10,7 +10,7 @@ // Check that an associated type cannot be bound in an expression path. -trait Foo { +trait Foo : ::std::marker::MarkerTrait { type A; fn bar() -> isize; } diff --git a/src/test/compile-fail/associated-types-issue-17359.rs b/src/test/compile-fail/associated-types-issue-17359.rs index fa09ae793bf..625f4cdb8ef 100644 --- a/src/test/compile-fail/associated-types-issue-17359.rs +++ b/src/test/compile-fail/associated-types-issue-17359.rs @@ -11,7 +11,7 @@ // Test that we do not ICE when an impl is missing an associated type (and that we report // a useful error, of course). -trait Trait { +trait Trait : ::std::marker::MarkerTrait { type Type; } diff --git a/src/test/compile-fail/associated-types-multiple-types-one-trait.rs b/src/test/compile-fail/associated-types-multiple-types-one-trait.rs index 9436f825de8..5632f148da6 100644 --- a/src/test/compile-fail/associated-types-multiple-types-one-trait.rs +++ b/src/test/compile-fail/associated-types-multiple-types-one-trait.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo { +trait Foo : ::std::marker::MarkerTrait { type X; type Y; } diff --git a/src/test/compile-fail/associated-types-no-suitable-supertrait.rs b/src/test/compile-fail/associated-types-no-suitable-supertrait.rs index a3f2850b294..2b84c38f80b 100644 --- a/src/test/compile-fail/associated-types-no-suitable-supertrait.rs +++ b/src/test/compile-fail/associated-types-no-suitable-supertrait.rs @@ -11,7 +11,7 @@ // Check that we get an error when you use `::Value` in // the trait definition but `Self` does not, in fact, implement `Get`. -trait Get { +trait Get : ::std::marker::MarkerTrait { type Value; } diff --git a/src/test/compile-fail/associated-types-path-2.rs b/src/test/compile-fail/associated-types-path-2.rs index 51a37b517dd..b9a62ff4e41 100644 --- a/src/test/compile-fail/associated-types-path-2.rs +++ b/src/test/compile-fail/associated-types-path-2.rs @@ -12,6 +12,8 @@ pub trait Foo { type A; + + fn dummy(&self) { } } impl Foo for i32 { diff --git a/src/test/compile-fail/associated-types-unconstrained.rs b/src/test/compile-fail/associated-types-unconstrained.rs index aecbf217a5b..8832028f9ab 100644 --- a/src/test/compile-fail/associated-types-unconstrained.rs +++ b/src/test/compile-fail/associated-types-unconstrained.rs @@ -10,7 +10,7 @@ // Check that an associated type cannot be bound in an expression path. -trait Foo { +trait Foo : ::std::marker::MarkerTrait { type A; fn bar() -> isize; } diff --git a/src/test/compile-fail/bad-mid-path-type-params.rs b/src/test/compile-fail/bad-mid-path-type-params.rs index c91849ca53e..3e02a11c378 100644 --- a/src/test/compile-fail/bad-mid-path-type-params.rs +++ b/src/test/compile-fail/bad-mid-path-type-params.rs @@ -10,13 +10,6 @@ // ignore-tidy-linelength -#![feature(no_std)] -#![no_std] -#![feature(lang_items)] - -#[lang="sized"] -pub trait Sized {} - struct S { contents: T, } diff --git a/src/test/compile-fail/bad-sized.rs b/src/test/compile-fail/bad-sized.rs index 69be6414e4c..1944acbe1f3 100644 --- a/src/test/compile-fail/bad-sized.rs +++ b/src/test/compile-fail/bad-sized.rs @@ -12,7 +12,7 @@ use std::cell::RefCell; -trait Trait {} +trait Trait : ::std::marker::MarkerTrait {} pub fn main() { let x: Vec = Vec::new(); 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 27d97d18c94..d4decb71349 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 @@ -10,6 +10,7 @@ use std::fmt::Show; use std::default::Default; +use std::marker::MarkerTrait; // Test that two blanket impls conflict (at least without negative // bounds). After all, some other crate could implement Even or Odd @@ -19,9 +20,9 @@ trait MyTrait { fn get(&self) -> usize; } -trait Even { } +trait Even : MarkerTrait { } -trait Odd { } +trait Odd : MarkerTrait { } impl Even for isize { } 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 0f233b78c72..b1ee1762b6e 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 @@ -19,9 +19,9 @@ trait MyTrait { fn get(&self) -> usize; } -trait Even { } +trait Even : ::std::marker::MarkerTrait { } -trait Odd { } +trait Odd : ::std::marker::MarkerTrait { } impl MyTrait for T { //~ ERROR E0119 fn get(&self) -> usize { 0 } diff --git a/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs b/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs index c9dfb8201a9..a225f6cf473 100644 --- a/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs +++ b/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs @@ -10,18 +10,18 @@ #![feature(optin_builtin_traits)] -trait MyTrait {} +trait MyTrait : ::std::marker::MarkerTrait {} -struct TestType; +struct TestType(::std::marker::PhantomData); -unsafe impl Send for TestType {} +unsafe impl Send for TestType {} //~^ ERROR conflicting implementations for trait `core::marker::Send` //~^^ ERROR conflicting implementations for trait `core::marker::Send` impl !Send for TestType {} //~^ ERROR conflicting implementations for trait `core::marker::Send` -unsafe impl Send for TestType {} +unsafe impl Send for TestType {} //~^ ERROR error: conflicting implementations for trait `core::marker::Send` impl !Send for TestType {} diff --git a/src/test/compile-fail/coherence-subtyping.rs b/src/test/compile-fail/coherence-subtyping.rs new file mode 100644 index 00000000000..897cb083f84 --- /dev/null +++ b/src/test/compile-fail/coherence-subtyping.rs @@ -0,0 +1,50 @@ +// 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. + +// Test that two distinct impls which match subtypes of one another +// yield coherence errors (or not) depending on the variance. + +trait Contravariant { + fn foo(&self) { } +} + +impl Contravariant for for<'a,'b> fn(&'a u8, &'b u8) { + //~^ ERROR E0119 +} + +impl Contravariant for for<'a> fn(&'a u8, &'a u8) { +} + +/////////////////////////////////////////////////////////////////////////// + +trait Covariant { + fn foo(&self) { } +} + +impl Covariant for for<'a,'b> fn(&'a u8, &'b u8) { + //~^ ERROR E0119 +} + +impl Covariant for for<'a> fn(&'a u8, &'a u8) { +} + +/////////////////////////////////////////////////////////////////////////// + +trait Invariant { + fn foo(&self) -> Self { } +} + +impl Invariant for for<'a,'b> fn(&'a u8, &'b u8) { +} + +impl Invariant for for<'a> fn(&'a u8, &'a u8) { +} + +fn main() { } diff --git a/src/test/compile-fail/cross-borrow-trait.rs b/src/test/compile-fail/cross-borrow-trait.rs index 86b7a8c8918..c97a9950d78 100644 --- a/src/test/compile-fail/cross-borrow-trait.rs +++ b/src/test/compile-fail/cross-borrow-trait.rs @@ -14,7 +14,7 @@ #![feature(box_syntax)] struct Foo; -trait Trait {} +trait Trait : ::std::marker::MarkerTrait {} impl Trait for Foo {} pub fn main() { diff --git a/src/test/compile-fail/destructure-trait-ref.rs b/src/test/compile-fail/destructure-trait-ref.rs index f2e068cc4ff..d8b3f297a11 100644 --- a/src/test/compile-fail/destructure-trait-ref.rs +++ b/src/test/compile-fail/destructure-trait-ref.rs @@ -14,7 +14,7 @@ #![feature(box_patterns)] #![feature(box_syntax)] -trait T {} +trait T : ::std::marker::MarkerTrait {} impl T for isize {} fn main() { diff --git a/src/test/compile-fail/dst-bad-coerce1.rs b/src/test/compile-fail/dst-bad-coerce1.rs index 2b96c5ebe12..6d9ba8d44c0 100644 --- a/src/test/compile-fail/dst-bad-coerce1.rs +++ b/src/test/compile-fail/dst-bad-coerce1.rs @@ -15,7 +15,7 @@ struct Fat { } struct Foo; -trait Bar {} +trait Bar : ::std::marker::MarkerTrait {} pub fn main() { // With a vec of isize. diff --git a/src/test/compile-fail/dst-bad-coerce2.rs b/src/test/compile-fail/dst-bad-coerce2.rs index 160197368d6..aa687266acb 100644 --- a/src/test/compile-fail/dst-bad-coerce2.rs +++ b/src/test/compile-fail/dst-bad-coerce2.rs @@ -15,7 +15,7 @@ struct Fat { } struct Foo; -trait Bar {} +trait Bar : ::std::marker::MarkerTrait {} impl Bar for Foo {} pub fn main() { diff --git a/src/test/compile-fail/dst-bad-coerce3.rs b/src/test/compile-fail/dst-bad-coerce3.rs index 347a2d2ecbe..46b89e1122a 100644 --- a/src/test/compile-fail/dst-bad-coerce3.rs +++ b/src/test/compile-fail/dst-bad-coerce3.rs @@ -15,7 +15,7 @@ struct Fat { } struct Foo; -trait Bar {} +trait Bar : ::std::marker::MarkerTrait {} impl Bar for Foo {} fn baz<'a>() { diff --git a/src/test/compile-fail/dst-bad-coercions.rs b/src/test/compile-fail/dst-bad-coercions.rs index b30eada162b..8ec1034bc4d 100644 --- a/src/test/compile-fail/dst-bad-coercions.rs +++ b/src/test/compile-fail/dst-bad-coercions.rs @@ -10,8 +10,10 @@ // Test implicit coercions involving DSTs and raw pointers. +use std::marker::MarkerTrait; + struct S; -trait T {} +trait T : MarkerTrait {} impl T for S {} struct Foo { diff --git a/src/test/compile-fail/dst-object-from-unsized-type.rs b/src/test/compile-fail/dst-object-from-unsized-type.rs index 87ff4291f50..a1f0dda671e 100644 --- a/src/test/compile-fail/dst-object-from-unsized-type.rs +++ b/src/test/compile-fail/dst-object-from-unsized-type.rs @@ -10,7 +10,7 @@ // Test that we cannot create objects from unsized types. -trait Foo {} +trait Foo : ::std::marker::MarkerTrait {} impl Foo for str {} fn test1(t: &T) { diff --git a/src/test/compile-fail/exclusive-drop-and-copy.rs b/src/test/compile-fail/exclusive-drop-and-copy.rs index 17453bc677f..f47f14d5879 100644 --- a/src/test/compile-fail/exclusive-drop-and-copy.rs +++ b/src/test/compile-fail/exclusive-drop-and-copy.rs @@ -20,7 +20,7 @@ impl Drop for Foo { } #[derive(Copy)] //~ ERROR the trait `Copy` may not be implemented -struct Bar; +struct Bar(::std::marker::PhantomData); #[unsafe_destructor] impl Drop for Bar { diff --git a/src/test/compile-fail/generic-impl-less-params-with-defaults.rs b/src/test/compile-fail/generic-impl-less-params-with-defaults.rs index 02f09749d61..9fea5e609d1 100644 --- a/src/test/compile-fail/generic-impl-less-params-with-defaults.rs +++ b/src/test/compile-fail/generic-impl-less-params-with-defaults.rs @@ -8,10 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Foo; +use std::marker; + +struct Foo( + marker::PhantomData<(A,B,C)>); impl Foo { - fn new() -> Foo {Foo} + fn new() -> Foo {Foo(marker::PhantomData)} } fn main() { diff --git a/src/test/compile-fail/generic-impl-more-params-with-defaults.rs b/src/test/compile-fail/generic-impl-more-params-with-defaults.rs index d88da2625c1..73c19aa012d 100644 --- a/src/test/compile-fail/generic-impl-more-params-with-defaults.rs +++ b/src/test/compile-fail/generic-impl-more-params-with-defaults.rs @@ -8,12 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker; + struct Heap; -struct Vec; +struct Vec( + marker::PhantomData<(T,A)>); impl Vec { - fn new() -> Vec {Vec} + fn new() -> Vec {Vec(marker::PhantomData)} } fn main() { diff --git a/src/test/compile-fail/generic-lifetime-trait-impl.rs b/src/test/compile-fail/generic-lifetime-trait-impl.rs index fc54002820e..9b9f09f4777 100644 --- a/src/test/compile-fail/generic-lifetime-trait-impl.rs +++ b/src/test/compile-fail/generic-lifetime-trait-impl.rs @@ -16,9 +16,12 @@ // // Regression test for issue #16218. -trait Bar<'a> {} +trait Bar<'a> { + fn dummy(&'a self); +} trait Foo<'a> { + fn dummy(&'a self) { } fn bar<'b, T: Bar<'b>>(self) -> &'b str; } diff --git a/src/test/compile-fail/generic-type-less-params-with-defaults.rs b/src/test/compile-fail/generic-type-less-params-with-defaults.rs index f25d8f99b8d..37737fda474 100644 --- a/src/test/compile-fail/generic-type-less-params-with-defaults.rs +++ b/src/test/compile-fail/generic-type-less-params-with-defaults.rs @@ -8,9 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker; + struct Heap; -struct Vec; +struct Vec( + marker::PhantomData<(T,A)>); fn main() { let _: Vec; //~ ERROR wrong number of type arguments: expected at least 1, found 0 diff --git a/src/test/compile-fail/generic-type-more-params-with-defaults.rs b/src/test/compile-fail/generic-type-more-params-with-defaults.rs index 19d303488ac..ad7e4f190c5 100644 --- a/src/test/compile-fail/generic-type-more-params-with-defaults.rs +++ b/src/test/compile-fail/generic-type-more-params-with-defaults.rs @@ -8,9 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker; + struct Heap; -struct Vec; +struct Vec( + marker::PhantomData<(T,A)>); fn main() { let _: Vec; diff --git a/src/test/compile-fail/generic-type-params-name-repr.rs b/src/test/compile-fail/generic-type-params-name-repr.rs index 3e34344d78b..a452cd35f94 100644 --- a/src/test/compile-fail/generic-type-params-name-repr.rs +++ b/src/test/compile-fail/generic-type-params-name-repr.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker; + struct A; struct B; struct C; -struct Foo; +struct Foo(marker::PhantomData<(T,U,V)>); -struct Hash; -struct HashMap>; +struct Hash(marker::PhantomData); +struct HashMap>(marker::PhantomData<(K,V,H)>); fn main() { // Ensure that the printed type doesn't include the default type params... diff --git a/src/test/compile-fail/issue-11515.rs b/src/test/compile-fail/issue-11515.rs index f0089b0ae5b..4ff574e939d 100644 --- a/src/test/compile-fail/issue-11515.rs +++ b/src/test/compile-fail/issue-11515.rs @@ -10,7 +10,7 @@ #![feature(box_syntax)] -struct Test<'s> { +struct Test { func: Box } diff --git a/src/test/compile-fail/issue-13853-2.rs b/src/test/compile-fail/issue-13853-2.rs index ea0d880f4a1..dc697e4784f 100644 --- a/src/test/compile-fail/issue-13853-2.rs +++ b/src/test/compile-fail/issue-13853-2.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait FromStructReader<'a> { } +use std::marker::PhantomFn; + +trait FromStructReader<'a> : PhantomFn<(Self,&'a ())> { } trait ResponseHook { fn get<'a, T: FromStructReader<'a>>(&'a self); } diff --git a/src/test/compile-fail/issue-13853-3.rs b/src/test/compile-fail/issue-13853-3.rs index f10c47b594e..7ca158c3e32 100644 --- a/src/test/compile-fail/issue-13853-3.rs +++ b/src/test/compile-fail/issue-13853-3.rs @@ -10,6 +10,8 @@ #![crate_type = "lib"] +use std::marker::PhantomData; + enum NodeContents<'a> { Children(Vec>), } @@ -22,11 +24,12 @@ impl<'a> Drop for NodeContents<'a> { struct Node<'a> { contents: NodeContents<'a>, + marker: PhantomData<&'a ()>, } impl<'a> Node<'a> { fn noName(contents: NodeContents<'a>) -> Node<'a> { - Node{ contents: contents,} + Node { contents: contents, marker: PhantomData } } } diff --git a/src/test/compile-fail/issue-13853.rs b/src/test/compile-fail/issue-13853.rs index 251da2c6b3e..cd3f337c4ab 100644 --- a/src/test/compile-fail/issue-13853.rs +++ b/src/test/compile-fail/issue-13853.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Node { +use std::marker::MarkerTrait; + +trait Node : MarkerTrait { fn zomg(); } diff --git a/src/test/compile-fail/issue-14285.rs b/src/test/compile-fail/issue-14285.rs index cbf4412a81d..3a5df9e805b 100644 --- a/src/test/compile-fail/issue-14285.rs +++ b/src/test/compile-fail/issue-14285.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo {} +trait Foo { + fn dummy(&self) { } +} struct A; diff --git a/src/test/compile-fail/issue-14853.rs b/src/test/compile-fail/issue-14853.rs index 51deb99a4f2..0b846651acf 100644 --- a/src/test/compile-fail/issue-14853.rs +++ b/src/test/compile-fail/issue-14853.rs @@ -9,8 +9,9 @@ // except according to those terms. use std::fmt::Debug; +use std::marker::MarkerTrait; -trait Str {} +trait Str : MarkerTrait {} trait Something { fn yay(_: Option, thing: &[T]); diff --git a/src/test/compile-fail/issue-16747.rs b/src/test/compile-fail/issue-16747.rs index 814b885e3aa..a213234b89b 100644 --- a/src/test/compile-fail/issue-16747.rs +++ b/src/test/compile-fail/issue-16747.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait ListItem<'a> { +use std::marker::MarkerTrait; + +trait ListItem<'a> : MarkerTrait { fn list_name() -> &'a str; } diff --git a/src/test/compile-fail/issue-17431-4.rs b/src/test/compile-fail/issue-17431-4.rs index 1e27f025564..22aaa796ad0 100644 --- a/src/test/compile-fail/issue-17431-4.rs +++ b/src/test/compile-fail/issue-17431-4.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Foo { foo: Option>> } +use std::marker; + +struct Foo { foo: Option>>, marker: marker::PhantomData } //~^ ERROR illegal recursive struct type; wrap the inner value in a box to make it representable impl Foo { fn bar(&self) {} } diff --git a/src/test/compile-fail/issue-17431-5.rs b/src/test/compile-fail/issue-17431-5.rs index d22d79ecaa5..cc9cc2e3c03 100644 --- a/src/test/compile-fail/issue-17431-5.rs +++ b/src/test/compile-fail/issue-17431-5.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker; + struct Foo { foo: Bar } -struct Bar { x: Bar } +struct Bar { x: Bar , marker: marker::PhantomData } //~^ ERROR illegal recursive struct type; wrap the inner value in a box to make it representable impl Foo { fn foo(&self) {} } diff --git a/src/test/compile-fail/issue-17551.rs b/src/test/compile-fail/issue-17551.rs index e037ba92b4a..5781cb74117 100644 --- a/src/test/compile-fail/issue-17551.rs +++ b/src/test/compile-fail/issue-17551.rs @@ -10,9 +10,11 @@ #![feature(unboxed_closures)] -struct B; +use std::marker; + +struct B(marker::PhantomData); fn main() { - let foo = B; //~ ERROR: unable to infer enough type information + let foo = B(marker::PhantomData); //~ ERROR unable to infer enough type information let closure = || foo; } diff --git a/src/test/compile-fail/issue-17904-2.rs b/src/test/compile-fail/issue-17904-2.rs new file mode 100644 index 00000000000..a33ec23a16a --- /dev/null +++ b/src/test/compile-fail/issue-17904-2.rs @@ -0,0 +1,16 @@ +// 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. + +// Test that we can parse a unit struct with a where clause, even if +// it leads to a error later on since `T` is unused. + +struct Foo where T: Copy; //~ ERROR parameter `T` is never used + +fn main() {} diff --git a/src/test/compile-fail/issue-18107.rs b/src/test/compile-fail/issue-18107.rs index 91689988f58..d5fb22bdebd 100644 --- a/src/test/compile-fail/issue-18107.rs +++ b/src/test/compile-fail/issue-18107.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker::MarkerTrait; - -pub trait AbstractRenderer {} +pub trait AbstractRenderer : MarkerTrait {} fn _create_render(_: &()) -> AbstractRenderer diff --git a/src/test/compile-fail/issue-18611.rs b/src/test/compile-fail/issue-18611.rs index a662e9ca98e..e81a576fa63 100644 --- a/src/test/compile-fail/issue-18611.rs +++ b/src/test/compile-fail/issue-18611.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker::MarkerTrait; + fn add_state(op: ::State) { //~^ ERROR the trait `HasState` is not implemented for the type `isize` } -trait HasState { +trait HasState : MarkerTrait { type State; } diff --git a/src/test/compile-fail/issue-18783.rs b/src/test/compile-fail/issue-18783.rs index 5ddf06add9d..13908bda9d8 100644 --- a/src/test/compile-fail/issue-18783.rs +++ b/src/test/compile-fail/issue-18783.rs @@ -26,6 +26,7 @@ fn ufcs() { Push::push(&c, box || y = 0); Push::push(&c, box || y = 0); +//~^ ERROR cannot borrow `y` as mutable more than once at a time } trait Push<'c> { diff --git a/src/test/compile-fail/issue-18819.rs b/src/test/compile-fail/issue-18819.rs index 3a9de741043..951d78410b8 100644 --- a/src/test/compile-fail/issue-18819.rs +++ b/src/test/compile-fail/issue-18819.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo { +use std::marker::MarkerTrait; + +trait Foo : MarkerTrait { type Item; } diff --git a/src/test/compile-fail/issue-19660.rs b/src/test/compile-fail/issue-19660.rs index 14601e67a77..77aba7335bd 100644 --- a/src/test/compile-fail/issue-19660.rs +++ b/src/test/compile-fail/issue-19660.rs @@ -13,8 +13,12 @@ #![feature(lang_items, start, no_std)] #![no_std] +#[lang="phantom_fn"] +trait PhantomFn { } +impl PhantomFn for U { } + #[lang = "sized"] -trait Sized {} +trait Sized : PhantomFn {} #[start] fn main(_: int, _: *const *const u8) -> int { diff --git a/src/test/compile-fail/issue-2063.rs b/src/test/compile-fail/issue-2063.rs index 00607f85034..aed395d17ea 100644 --- a/src/test/compile-fail/issue-2063.rs +++ b/src/test/compile-fail/issue-2063.rs @@ -12,10 +12,11 @@ // cause compiler to loop. Note that no instances // of such a type could ever be constructed. +use std::marker::MarkerTrait; struct t(Box); //~ ERROR this type cannot be instantiated -trait to_str_2 { +trait to_str_2 : MarkerTrait { fn my_to_string() -> String; } diff --git a/src/test/compile-fail/issue-20831-debruijn.rs b/src/test/compile-fail/issue-20831-debruijn.rs index aaf45f27398..5b623ac377b 100644 --- a/src/test/compile-fail/issue-20831-debruijn.rs +++ b/src/test/compile-fail/issue-20831-debruijn.rs @@ -13,10 +13,11 @@ // below. Note that changing to a named lifetime made the problem go // away. -use std::ops::{Shl, Shr}; use std::cell::RefCell; +use std::marker::MarkerTrait; +use std::ops::{Shl, Shr}; -pub trait Subscriber { +pub trait Subscriber : MarkerTrait { type Input; } diff --git a/src/test/compile-fail/issue-2611-4.rs b/src/test/compile-fail/issue-2611-4.rs index 31796e5e20c..24cc0099b89 100644 --- a/src/test/compile-fail/issue-2611-4.rs +++ b/src/test/compile-fail/issue-2611-4.rs @@ -12,7 +12,7 @@ // than the trait method it's implementing trait A { - fn b(x: C) -> C; + fn b(&self, x: C) -> C; } struct E { @@ -20,7 +20,7 @@ struct E { } impl A for E { - fn b(_x: F) -> F { panic!() } + fn b(&self, _x: F) -> F { panic!() } //~^ ERROR `F : core::marker::Sync` appears on the impl method } diff --git a/src/test/compile-fail/issue-3008-3.rs b/src/test/compile-fail/issue-3008-3.rs index a338a01690d..af6cee1f107 100644 --- a/src/test/compile-fail/issue-3008-3.rs +++ b/src/test/compile-fail/issue-3008-3.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker; + enum E1 { V1(E2), } -enum E2 { V2(E2), } +enum E2 { V2(E2, marker::PhantomData), } //~^ ERROR illegal recursive enum type; wrap the inner value in a box to make it representable impl E1 { fn foo(&self) {} } diff --git a/src/test/compile-fail/issue-4972.rs b/src/test/compile-fail/issue-4972.rs index 9a398796d2a..f384dba7c9e 100644 --- a/src/test/compile-fail/issue-4972.rs +++ b/src/test/compile-fail/issue-4972.rs @@ -11,7 +11,9 @@ #![feature(box_patterns)] #![feature(box_syntax)] -trait MyTrait { } +trait MyTrait { + fn dummy(&self) {} +} pub enum TraitWrapper { A(Box), diff --git a/src/test/compile-fail/issue-5035-2.rs b/src/test/compile-fail/issue-5035-2.rs index 9e324cdd61e..d316b44794a 100644 --- a/src/test/compile-fail/issue-5035-2.rs +++ b/src/test/compile-fail/issue-5035-2.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait I {} +use std::marker::MarkerTrait; + +trait I : MarkerTrait {} type K = I+'static; fn foo(_x: K) {} //~ ERROR: the trait `core::marker::Sized` is not implemented diff --git a/src/test/compile-fail/issue-5543.rs b/src/test/compile-fail/issue-5543.rs index cf98f1572e5..eccbc789660 100644 --- a/src/test/compile-fail/issue-5543.rs +++ b/src/test/compile-fail/issue-5543.rs @@ -10,7 +10,9 @@ #![feature(box_syntax)] -trait Foo {} +use std::marker::MarkerTrait; + +trait Foo : MarkerTrait {} impl Foo for u8 {} fn main() { diff --git a/src/test/compile-fail/issue-5883.rs b/src/test/compile-fail/issue-5883.rs index 9ff957b6e6d..b0db9906195 100644 --- a/src/test/compile-fail/issue-5883.rs +++ b/src/test/compile-fail/issue-5883.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait A {} +use std::marker::MarkerTrait; + +trait A : MarkerTrait {} struct Struct { r: A+'static @@ -20,6 +22,6 @@ fn new_struct(r: A+'static) Struct { r: r } } -trait Curve {} +trait Curve : MarkerTrait {} enum E {X(Curve+'static)} fn main() {} diff --git a/src/test/compile-fail/issue-6458.rs b/src/test/compile-fail/issue-6458.rs index efa3100360b..0bf9a3c2d48 100644 --- a/src/test/compile-fail/issue-6458.rs +++ b/src/test/compile-fail/issue-6458.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub struct TypeWithState; +use std::marker; + +pub struct TypeWithState(marker::PhantomData); pub struct MyState; pub fn foo(_: TypeWithState) {} pub fn bar() { - foo(TypeWithState); //~ ERROR type annotations required + foo(TypeWithState(marker::PhantomData)); //~ ERROR type annotations required } fn main() { diff --git a/src/test/compile-fail/issue-7575.rs b/src/test/compile-fail/issue-7575.rs index 9e6000c050a..b6643f43952 100644 --- a/src/test/compile-fail/issue-7575.rs +++ b/src/test/compile-fail/issue-7575.rs @@ -10,12 +10,14 @@ // Test the mechanism for warning about possible missing `self` declarations. +use std::marker::MarkerTrait; + trait CtxtFn { fn f8(self, usize) -> usize; fn f9(usize) -> usize; //~ NOTE candidate } -trait OtherTrait { +trait OtherTrait : MarkerTrait { fn f9(usize) -> usize; //~ NOTE candidate } @@ -24,7 +26,7 @@ trait OtherTrait { // declaration to match against, so we wind up prisizeing it as a // candidate. This seems not unreasonable -- perhaps the user meant to // implement it, after all. -trait UnusedTrait { +trait UnusedTrait : MarkerTrait { fn f9(usize) -> usize; //~ NOTE candidate } @@ -52,7 +54,7 @@ impl Myisize { } } -trait ManyImplTrait { +trait ManyImplTrait : MarkerTrait { fn is_str() -> bool { //~ NOTE candidate false } diff --git a/src/test/compile-fail/issue-8727.rs b/src/test/compile-fail/issue-8727.rs index d1a86d334cb..72da6dcaa6c 100644 --- a/src/test/compile-fail/issue-8727.rs +++ b/src/test/compile-fail/issue-8727.rs @@ -13,16 +13,12 @@ // Verify the compiler fails with an error on infinite function // recursions. -struct Data(Box>); - -fn generic( _ : Vec<(Data,T)> ) { - let rec : Vec<(Data,(bool,T))> = Vec::new(); - generic( rec ); +fn generic() { + generic::>(); } fn main () { // Use generic at least once to trigger instantiation. - let input : Vec<(Data,())> = Vec::new(); - generic(input); + generic::(); } diff --git a/src/test/compile-fail/kindck-copy.rs b/src/test/compile-fail/kindck-copy.rs index 56f83d93008..74e372e41eb 100644 --- a/src/test/compile-fail/kindck-copy.rs +++ b/src/test/compile-fail/kindck-copy.rs @@ -10,12 +10,12 @@ // Test which of the builtin types are considered POD. - +use std::marker::MarkerTrait; use std::rc::Rc; fn assert_copy() { } -trait Dummy { } +trait Dummy : MarkerTrait { } #[derive(Copy)] struct MyStruct { diff --git a/src/test/compile-fail/kindck-impl-type-params-2.rs b/src/test/compile-fail/kindck-impl-type-params-2.rs index 2731be7308a..b575144f637 100644 --- a/src/test/compile-fail/kindck-impl-type-params-2.rs +++ b/src/test/compile-fail/kindck-impl-type-params-2.rs @@ -10,7 +10,9 @@ #![feature(box_syntax)] -trait Foo { +use std::marker::MarkerTrait; + +trait Foo : MarkerTrait { } impl Foo for T { diff --git a/src/test/compile-fail/kindck-impl-type-params.rs b/src/test/compile-fail/kindck-impl-type-params.rs index d5276efa8be..dffc8fa2abd 100644 --- a/src/test/compile-fail/kindck-impl-type-params.rs +++ b/src/test/compile-fail/kindck-impl-type-params.rs @@ -13,40 +13,44 @@ #![feature(box_syntax)] -struct S; +use std::marker; -trait Gettable {} +struct S(marker::PhantomData); + +trait Gettable { + fn get(&self) -> T { panic!() } +} impl Gettable for S {} fn f(val: T) { - let t: S = S; + let t: S = S(marker::PhantomData); let a = &t as &Gettable; //~^ ERROR the trait `core::marker::Send` is not implemented //~^^ ERROR the trait `core::marker::Copy` is not implemented } fn g(val: T) { - let t: S = S; + let t: S = S(marker::PhantomData); let a: &Gettable = &t; //~^ ERROR the trait `core::marker::Send` is not implemented //~^^ ERROR the trait `core::marker::Copy` is not implemented } fn foo<'a>() { - let t: S<&'a isize> = S; + let t: S<&'a isize> = S(marker::PhantomData); let a = &t as &Gettable<&'a isize>; - //~^ ERROR the type `&'a isize` does not fulfill the required lifetime + //~^ ERROR cannot infer } fn foo2<'a>() { - let t: Box> = box S; + let t: Box> = box S(marker::PhantomData); let a = t as Box>; //~^ ERROR the trait `core::marker::Copy` is not implemented } fn foo3<'a>() { - let t: Box> = box S; + let t: Box> = box S(marker::PhantomData); let a: Box> = t; //~^ ERROR the trait `core::marker::Copy` is not implemented } diff --git a/src/test/compile-fail/kindck-send-object.rs b/src/test/compile-fail/kindck-send-object.rs index 570f7ad7fe3..0c68401bb2b 100644 --- a/src/test/compile-fail/kindck-send-object.rs +++ b/src/test/compile-fail/kindck-send-object.rs @@ -12,8 +12,10 @@ // in this file all test the "kind" violates detected during kindck. // See all `regions-bounded-by-send.rs` +use std::marker::MarkerTrait; + fn assert_send() { } -trait Dummy { } +trait Dummy : MarkerTrait { } trait Message : Send { } // careful with object types, who knows what they close over... diff --git a/src/test/compile-fail/kindck-send-object1.rs b/src/test/compile-fail/kindck-send-object1.rs index 48d5215b708..f86eac8b16b 100644 --- a/src/test/compile-fail/kindck-send-object1.rs +++ b/src/test/compile-fail/kindck-send-object1.rs @@ -12,8 +12,10 @@ // is broken into two parts because some errors occur in distinct // phases in the compiler. See kindck-send-object2.rs as well! +use std::marker::MarkerTrait; + fn assert_send() { } -trait Dummy { } +trait Dummy : MarkerTrait { } // careful with object types, who knows what they close over... fn test51<'a>() { diff --git a/src/test/compile-fail/kindck-send-object2.rs b/src/test/compile-fail/kindck-send-object2.rs index d3d166e2a69..08516e67318 100644 --- a/src/test/compile-fail/kindck-send-object2.rs +++ b/src/test/compile-fail/kindck-send-object2.rs @@ -10,8 +10,10 @@ // Continue kindck-send-object1.rs. +use std::marker::MarkerTrait; + fn assert_send() { } -trait Dummy { } +trait Dummy : MarkerTrait { } fn test50() { assert_send::<&'static Dummy>(); //~ ERROR the trait `core::marker::Sync` is not implemented diff --git a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-3.rs b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-3.rs index 04c5b223cb8..66d8927ee51 100644 --- a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-3.rs +++ b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-3.rs @@ -10,7 +10,9 @@ // ignore-tidy-linelength -struct Bar<'x, 'y, 'z> { bar: &'y i32, baz: i32 } +use std::marker::PhantomData; + +struct Bar<'x, 'y, 'z> { bar: &'y i32, baz: i32, marker: PhantomData<(&'x(),&'y(),&'z())> } fn bar1<'a>(x: &Bar) -> (&'a i32, &'a i32, &'a i32) { //~^ HELP: consider using an explicit lifetime parameter as shown: fn bar1<'b, 'c, 'a>(x: &'a Bar<'b, 'a, 'c>) -> (&'a i32, &'a i32, &'a i32) (x.bar, &x.baz, &x.baz) diff --git a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs index c60e321219b..a85776a938b 100644 --- a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs +++ b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs @@ -10,7 +10,9 @@ // ignore-tidy-linelength -struct Foo<'x> { bar: isize } +use std::marker::PhantomData; + +struct Foo<'x> { bar: isize, marker: PhantomData<&'x ()> } fn foo1<'a>(x: &Foo) -> &'a isize { //~^ HELP: consider using an explicit lifetime parameter as shown: fn foo1<'a>(x: &'a Foo) -> &'a isize &x.bar //~ ERROR: cannot infer diff --git a/src/test/compile-fail/lint-missing-doc.rs b/src/test/compile-fail/lint-missing-doc.rs index 3b96fd64fa2..73a58741bbb 100644 --- a/src/test/compile-fail/lint-missing-doc.rs +++ b/src/test/compile-fail/lint-missing-doc.rs @@ -47,20 +47,26 @@ fn foo3() {} /// dox pub trait A { /// dox - fn foo(); + fn foo(&self); /// dox - fn foo_with_impl() {} + fn foo_with_impl(&self) {} } + #[allow(missing_docs)] trait B { - fn foo(); - fn foo_with_impl() {} + fn foo(&self); + fn foo_with_impl(&self) {} } + pub trait C { //~ ERROR: missing documentation - fn foo(); //~ ERROR: missing documentation - fn foo_with_impl() {} //~ ERROR: missing documentation + fn foo(&self); //~ ERROR: missing documentation + fn foo_with_impl(&self) {} //~ ERROR: missing documentation +} + +#[allow(missing_docs)] +pub trait D { + fn dummy(&self) { } } -#[allow(missing_docs)] pub trait D {} impl Foo { pub fn foo() {} diff --git a/src/test/compile-fail/lint-non-camel-case-types.rs b/src/test/compile-fail/lint-non-camel-case-types.rs index 70d6b240985..9f58d5791cb 100644 --- a/src/test/compile-fail/lint-non-camel-case-types.rs +++ b/src/test/compile-fail/lint-non-camel-case-types.rs @@ -30,6 +30,7 @@ enum Foo5 { } trait foo6 { //~ ERROR trait `foo6` should have a camel case name such as `Foo6` + fn dummy(&self) { } } fn f(_: ty) {} //~ ERROR type parameter `ty` should have a camel case name such as `Ty` diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs index f9cdfa4f7d6..88f2cbdea6d 100644 --- a/src/test/compile-fail/lint-stability.rs +++ b/src/test/compile-fail/lint-stability.rs @@ -341,7 +341,9 @@ mod this_crate { #[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] - pub trait DeprecatedTrait {} + pub trait DeprecatedTrait { + fn dummy(&self) { } + } struct S; diff --git a/src/test/compile-fail/lint-visible-private-types.rs b/src/test/compile-fail/lint-visible-private-types.rs index 8cf375f80fb..918b4ee209c 100644 --- a/src/test/compile-fail/lint-visible-private-types.rs +++ b/src/test/compile-fail/lint-visible-private-types.rs @@ -12,8 +12,10 @@ #![allow(dead_code)] #![crate_type="lib"] -struct Private; -pub struct Public; +use std::marker; + +struct Private(marker::PhantomData); +pub struct Public(marker::PhantomData); impl Private> { pub fn a(&self) -> Private { panic!() } @@ -103,7 +105,7 @@ impl PrivTrait for (Private,) { fn bar(&self) -> Private { panic!() } } -pub trait ParamTrait { +pub trait ParamTrait : marker::MarkerTrait { fn foo() -> T; } diff --git a/src/test/compile-fail/liveness-use-after-send.rs b/src/test/compile-fail/liveness-use-after-send.rs index a49339ecd7f..03d8d62e0b4 100644 --- a/src/test/compile-fail/liveness-use-after-send.rs +++ b/src/test/compile-fail/liveness-use-after-send.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker; + fn send(ch: _chan, data: T) { println!("{:?}", ch); println!("{:?}", data); @@ -15,7 +17,7 @@ fn send(ch: _chan, data: T) { } #[derive(Debug)] -struct _chan(isize); +struct _chan(isize, marker::PhantomData); // Tests that "log(debug, message);" is flagged as using // message after the send deinitializes it diff --git a/src/test/compile-fail/map-types.rs b/src/test/compile-fail/map-types.rs index ba2205f5868..6e8719eeace 100644 --- a/src/test/compile-fail/map-types.rs +++ b/src/test/compile-fail/map-types.rs @@ -14,7 +14,10 @@ extern crate collections; use std::collections::HashMap; -trait Map {} +trait Map +{ + fn get(&self, k: K) -> V { panic!() } +} impl Map for HashMap {} diff --git a/src/test/compile-fail/method-ambig-one-trait-coerce.rs b/src/test/compile-fail/method-ambig-one-trait-coerce.rs deleted file mode 100644 index cb5da4bb547..00000000000 --- a/src/test/compile-fail/method-ambig-one-trait-coerce.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that when we pick a trait based on coercion, versus subtyping, -// we consider all possible coercions equivalent and don't try to pick -// a best one. - -trait Object { } - -trait foo { - fn foo(self) -> isize; -} - -impl foo for Box { - fn foo(self) -> isize {1} -} - -impl foo for Box { - fn foo(self) -> isize {2} -} - -fn test1(x: Box) { - // FIXME(#18737) -- we ought to consider this to be ambiguous, - // since we could coerce to either impl. However, what actually - // happens is that we consider both impls applicable because of - // incorrect subtyping relation. We then decide to call this a - // call to the `foo` trait, leading to the following error - // message. - - x.foo(); //~ ERROR `foo` is not implemented -} - -fn test2(x: Box) { - // Not ambiguous because it is a precise match: - x.foo(); -} - -fn test3(x: Box) { - // Not ambiguous because it is a precise match: - x.foo(); -} - -fn main() { } diff --git a/src/test/compile-fail/object-does-not-impl-trait.rs b/src/test/compile-fail/object-does-not-impl-trait.rs index cfaf149a49c..607ab13d122 100644 --- a/src/test/compile-fail/object-does-not-impl-trait.rs +++ b/src/test/compile-fail/object-does-not-impl-trait.rs @@ -11,8 +11,9 @@ // Test that an object type `Box` is not considered to implement the // trait `Foo`. Issue #5087. +use std::marker::MarkerTrait; -trait Foo {} +trait Foo : MarkerTrait {} fn take_foo(f: F) {} fn take_object(f: Box) { take_foo(f); } //~^ ERROR the trait `Foo` is not implemented diff --git a/src/test/compile-fail/object-lifetime-default-mybox.rs b/src/test/compile-fail/object-lifetime-default-mybox.rs index c107c8d131d..23ddea4499a 100644 --- a/src/test/compile-fail/object-lifetime-default-mybox.rs +++ b/src/test/compile-fail/object-lifetime-default-mybox.rs @@ -37,7 +37,6 @@ fn load1<'a,'b>(a: &'a MyBox, a //~^ ERROR cannot infer //~| ERROR mismatched types - //~| ERROR mismatched types } fn main() { diff --git a/src/test/compile-fail/object-safety-no-static.rs b/src/test/compile-fail/object-safety-no-static.rs index 6a010d49692..aae829ec7b5 100644 --- a/src/test/compile-fail/object-safety-no-static.rs +++ b/src/test/compile-fail/object-safety-no-static.rs @@ -11,7 +11,7 @@ // Check that we correctly prevent users from making trait objects // from traits with static methods. -trait Foo { +trait Foo : ::std::marker::MarkerTrait { fn foo(); } diff --git a/src/test/compile-fail/on-unimplemented-bad-anno.rs b/src/test/compile-fail/on-unimplemented-bad-anno.rs index dda534cc489..7538b1c85e5 100644 --- a/src/test/compile-fail/on-unimplemented-bad-anno.rs +++ b/src/test/compile-fail/on-unimplemented-bad-anno.rs @@ -13,8 +13,12 @@ #![allow(unused)] +use std::marker; + #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"] -trait Foo{} +trait Foo + : marker::PhantomFn<(Self,Bar,Baz,Quux)> +{} #[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an iterator over elements of type `{A}`"] trait MyFromIterator { @@ -23,15 +27,21 @@ trait MyFromIterator { } #[rustc_on_unimplemented] //~ ERROR this attribute must have a value -trait BadAnnotation1 {} +trait BadAnnotation1 + : marker::MarkerTrait +{} #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"] //~^ ERROR there is no type parameter C on trait BadAnnotation2 -trait BadAnnotation2 {} +trait BadAnnotation2 + : marker::PhantomFn<(Self,A,B)> +{} #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"] //~^ only named substitution parameters are allowed -trait BadAnnotation3 {} +trait BadAnnotation3 + : marker::PhantomFn<(Self,A,B)> +{} pub fn main() { } diff --git a/src/test/compile-fail/on-unimplemented.rs b/src/test/compile-fail/on-unimplemented.rs index 7b406afcf1f..2447d086422 100644 --- a/src/test/compile-fail/on-unimplemented.rs +++ b/src/test/compile-fail/on-unimplemented.rs @@ -11,8 +11,12 @@ #![feature(on_unimplemented)] +use std::marker; + #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"] -trait Foo{} +trait Foo + : marker::PhantomFn<(Self,Bar,Baz,Quux)> +{} fn foobar>() -> T { diff --git a/src/test/compile-fail/orphan-check-diagnostics.rs b/src/test/compile-fail/orphan-check-diagnostics.rs index ff5c101b917..8201565c331 100644 --- a/src/test/compile-fail/orphan-check-diagnostics.rs +++ b/src/test/compile-fail/orphan-check-diagnostics.rs @@ -15,7 +15,7 @@ extern crate orphan_check_diagnostics; use orphan_check_diagnostics::RemoteTrait; -trait LocalTrait {} +trait LocalTrait { fn dummy(&self) { } } impl RemoteTrait for T where T: LocalTrait {} //~^ ERROR type parameter `T` must be used as the type parameter for some local type diff --git a/src/test/compile-fail/priv-in-bad-locations.rs b/src/test/compile-fail/priv-in-bad-locations.rs index db649ed0cc6..43d112b8aa0 100644 --- a/src/test/compile-fail/priv-in-bad-locations.rs +++ b/src/test/compile-fail/priv-in-bad-locations.rs @@ -14,7 +14,7 @@ pub extern { } trait A { - fn foo() {} + fn foo(&self) {} } struct B; @@ -22,7 +22,7 @@ struct B; pub impl B {} //~ ERROR: unnecessary visibility pub impl A for B { //~ ERROR: unnecessary visibility - pub fn foo() {} //~ ERROR: unnecessary visibility + pub fn foo(&self) {} //~ ERROR: unnecessary visibility } pub fn main() {} diff --git a/src/test/compile-fail/privacy-ns2.rs b/src/test/compile-fail/privacy-ns2.rs index 7fe0574ab7d..67bb566ea68 100644 --- a/src/test/compile-fail/privacy-ns2.rs +++ b/src/test/compile-fail/privacy-ns2.rs @@ -17,7 +17,9 @@ // public type, private value pub mod foo1 { - pub trait Bar { + use std::marker::MarkerTrait; + + pub trait Bar : MarkerTrait { } pub struct Baz; @@ -39,7 +41,7 @@ fn test_list1() { // private type, public value pub mod foo2 { - trait Bar { + trait Bar : ::std::marker::MarkerTrait { } pub struct Baz; @@ -60,7 +62,7 @@ fn test_list2() { // neither public pub mod foo3 { - trait Bar { + trait Bar : ::std::marker::MarkerTrait { } pub struct Baz; diff --git a/src/test/compile-fail/privacy1.rs b/src/test/compile-fail/privacy1.rs index 7ebbcc2809a..1ae79adbad7 100644 --- a/src/test/compile-fail/privacy1.rs +++ b/src/test/compile-fail/privacy1.rs @@ -11,11 +11,15 @@ #![feature(lang_items, start, no_std)] #![no_std] // makes debugging this test *a lot* easier (during resolve) +#[lang="phantom_fn"] +pub trait PhantomFn { } +impl PhantomFn for U { } + #[lang="sized"] -pub trait Sized {} +pub trait Sized : PhantomFn {} #[lang="copy"] -pub trait Copy {} +pub trait Copy : PhantomFn {} mod bar { // shouldn't bring in too much diff --git a/src/test/compile-fail/privacy4.rs b/src/test/compile-fail/privacy4.rs index bcb46663aa8..adce93af079 100644 --- a/src/test/compile-fail/privacy4.rs +++ b/src/test/compile-fail/privacy4.rs @@ -11,8 +11,12 @@ #![feature(lang_items, start, no_std)] #![no_std] // makes debugging this test *a lot* easier (during resolve) -#[lang = "sized"] pub trait Sized {} -#[lang="copy"] pub trait Copy {} +#[lang="phantom_fn"] +pub trait PhantomFn { } +impl PhantomFn for U { } + +#[lang = "sized"] pub trait Sized : PhantomFn {} +#[lang="copy"] pub trait Copy : PhantomFn {} // Test to make sure that private items imported through globs remain private // when they're used. diff --git a/src/test/compile-fail/region-object-lifetime-in-coercion.rs b/src/test/compile-fail/region-object-lifetime-in-coercion.rs index 20cc624ab19..2da414befd8 100644 --- a/src/test/compile-fail/region-object-lifetime-in-coercion.rs +++ b/src/test/compile-fail/region-object-lifetime-in-coercion.rs @@ -13,7 +13,7 @@ #![feature(box_syntax)] -trait Foo {} +trait Foo : ::std::marker::MarkerTrait {} impl<'a> Foo for &'a [u8] {} fn a(v: &[u8]) -> Box { diff --git a/src/test/compile-fail/regions-assoc-type-region-bound-in-trait-not-met.rs b/src/test/compile-fail/regions-assoc-type-region-bound-in-trait-not-met.rs index f833361e3b5..f921eccef1f 100644 --- a/src/test/compile-fail/regions-assoc-type-region-bound-in-trait-not-met.rs +++ b/src/test/compile-fail/regions-assoc-type-region-bound-in-trait-not-met.rs @@ -11,7 +11,10 @@ // Test that the compiler checks that arbitrary region bounds declared // in the trait must be satisfied on the impl. Issue #20890. -trait Foo<'a> { type Value: 'a; } +trait Foo<'a> { + type Value: 'a; + fn dummy(&'a self) { } +} impl<'a> Foo<'a> for &'a i16 { // OK. diff --git a/src/test/compile-fail/regions-assoc-type-static-bound-in-trait-not-met.rs b/src/test/compile-fail/regions-assoc-type-static-bound-in-trait-not-met.rs index 0871d8b01f6..1cf83b8ac58 100644 --- a/src/test/compile-fail/regions-assoc-type-static-bound-in-trait-not-met.rs +++ b/src/test/compile-fail/regions-assoc-type-static-bound-in-trait-not-met.rs @@ -11,7 +11,10 @@ // Test that the compiler checks that the 'static bound declared in // the trait must be satisfied on the impl. Issue #20890. -trait Foo { type Value: 'static; } +trait Foo { + type Value: 'static; + fn dummy(&self) { } +} impl<'a> Foo for &'a i32 { //~^ ERROR cannot infer diff --git a/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs b/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs index a3c38dff6b0..278ccd3c119 100644 --- a/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs +++ b/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs @@ -21,10 +21,9 @@ pub trait Foo<'a, 't> { fn has_bound<'b:'a>(self, b: Inv<'b>); fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); fn okay_bound<'b,'c,'d:'a+'b+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); - fn another_bound<'x: 'a>(self, x: Inv<'x>); + fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>); } - impl<'a, 't> Foo<'a, 't> for &'a isize { fn no_bound<'b:'a>(self, b: Inv<'b>) { //~^ ERROR lifetime parameters or bounds on method `no_bound` do not match @@ -51,7 +50,7 @@ impl<'a, 't> Foo<'a, 't> for &'a isize { fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) { } - fn another_bound<'x: 't>(self, x: Inv<'x>) {} + fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) {} } fn main() { } diff --git a/src/test/compile-fail/regions-bounded-method-type-parameters-trait-bound.rs b/src/test/compile-fail/regions-bounded-method-type-parameters-trait-bound.rs index 74c2c6e584b..f13d8a60894 100644 --- a/src/test/compile-fail/regions-bounded-method-type-parameters-trait-bound.rs +++ b/src/test/compile-fail/regions-bounded-method-type-parameters-trait-bound.rs @@ -8,16 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, no_std)] -#![no_std] - // Check that explicit region bounds are allowed on the various // nominal types (but not on other types) and that they are type // checked. -#[lang="sized"] -trait Sized { } - struct Inv<'a> { // invariant w/r/t 'a x: &'a mut &'a isize } diff --git a/src/test/compile-fail/regions-close-associated-type-into-object.rs b/src/test/compile-fail/regions-close-associated-type-into-object.rs index 8a03f36972d..979c1e997d0 100644 --- a/src/test/compile-fail/regions-close-associated-type-into-object.rs +++ b/src/test/compile-fail/regions-close-associated-type-into-object.rs @@ -10,7 +10,9 @@ #![feature(box_syntax)] -trait X {} +use std::marker::MarkerTrait; + +trait X : MarkerTrait {} trait Iter { type Item: X; diff --git a/src/test/compile-fail/regions-close-object-into-object-1.rs b/src/test/compile-fail/regions-close-object-into-object-1.rs index 7a0e3cf4611..7bbce7dad53 100644 --- a/src/test/compile-fail/regions-close-object-into-object-1.rs +++ b/src/test/compile-fail/regions-close-object-into-object-1.rs @@ -11,13 +11,16 @@ #![feature(box_syntax)] #![allow(warnings)] -trait A {} +use std::marker::PhantomFn; + +trait A : PhantomFn<(Self,T)> { } struct B<'a, T>(&'a (A+'a)); -trait X {} +trait X : ::std::marker::MarkerTrait {} + impl<'a, T> X for B<'a, T> {} -fn f<'a, T, U>(v: Box+'static>) -> Box { +fn f<'a, T:'static, U>(v: Box+'static>) -> Box { box B(&*v) as Box //~ ERROR `*v` does not live long enough } diff --git a/src/test/compile-fail/regions-close-object-into-object-2.rs b/src/test/compile-fail/regions-close-object-into-object-2.rs index 7861fb95fef..6de49020a6f 100644 --- a/src/test/compile-fail/regions-close-object-into-object-2.rs +++ b/src/test/compile-fail/regions-close-object-into-object-2.rs @@ -10,10 +10,12 @@ #![feature(box_syntax)] -trait A {} +use std::marker::PhantomFn; + +trait A : PhantomFn<(Self,T)> { } struct B<'a, T>(&'a (A+'a)); -trait X {} +trait X : PhantomFn {} impl<'a, T> X for B<'a, T> {} fn g<'a, T: 'static>(v: Box+'a>) -> Box { diff --git a/src/test/compile-fail/regions-close-object-into-object-3.rs b/src/test/compile-fail/regions-close-object-into-object-3.rs index 31354de2a27..e22d0c7d0a4 100644 --- a/src/test/compile-fail/regions-close-object-into-object-3.rs +++ b/src/test/compile-fail/regions-close-object-into-object-3.rs @@ -11,10 +11,12 @@ #![feature(box_syntax)] #![allow(warnings)] -trait A {} +use std::marker::PhantomFn; + +trait A : PhantomFn<(Self,T)> {} struct B<'a, T>(&'a (A+'a)); -trait X {} +trait X : PhantomFn {} impl<'a, T> X for B<'a, T> {} fn h<'a, T, U>(v: Box+'static>) -> Box { diff --git a/src/test/compile-fail/regions-close-object-into-object-4.rs b/src/test/compile-fail/regions-close-object-into-object-4.rs index c60975f97e1..147a575d38c 100644 --- a/src/test/compile-fail/regions-close-object-into-object-4.rs +++ b/src/test/compile-fail/regions-close-object-into-object-4.rs @@ -10,10 +10,12 @@ #![feature(box_syntax)] -trait A {} +use std::marker::PhantomFn; + +trait A : PhantomFn<(Self,T)> {} struct B<'a, T>(&'a (A+'a)); -trait X {} +trait X : PhantomFn {} impl<'a, T> X for B<'a, T> {} fn i<'a, T, U>(v: Box+'a>) -> Box { diff --git a/src/test/compile-fail/regions-close-object-into-object-5.rs b/src/test/compile-fail/regions-close-object-into-object-5.rs new file mode 100644 index 00000000000..05c6c6d9f9e --- /dev/null +++ b/src/test/compile-fail/regions-close-object-into-object-5.rs @@ -0,0 +1,32 @@ +// 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. + +#![feature(box_syntax)] +#![allow(warnings)] + +use std::marker::MarkerTrait; + +trait A +{ + fn get(&self) -> T { panic!() } +} + +struct B<'a, T>(&'a (A+'a)); + +trait X : MarkerTrait {} + +impl<'a, T> X for B<'a, T> {} + +fn f<'a, T, U>(v: Box+'static>) -> Box { + box B(&*v) as Box //~ ERROR the parameter type `T` may not live long enough +} + +fn main() {} + diff --git a/src/test/compile-fail/regions-close-over-borrowed-ref-in-obj.rs b/src/test/compile-fail/regions-close-over-borrowed-ref-in-obj.rs index 25b8137d29c..2341d2397c9 100644 --- a/src/test/compile-fail/regions-close-over-borrowed-ref-in-obj.rs +++ b/src/test/compile-fail/regions-close-over-borrowed-ref-in-obj.rs @@ -10,7 +10,9 @@ #![feature(box_syntax)] -trait Foo { } +use std::marker::MarkerTrait; + +trait Foo : MarkerTrait { } impl<'a> Foo for &'a isize { } diff --git a/src/test/compile-fail/regions-close-param-into-object.rs b/src/test/compile-fail/regions-close-param-into-object.rs index 74b36958c92..9ad49a6703e 100644 --- a/src/test/compile-fail/regions-close-param-into-object.rs +++ b/src/test/compile-fail/regions-close-param-into-object.rs @@ -10,7 +10,7 @@ #![feature(box_syntax)] -trait X {} +trait X : ::std::marker::MarkerTrait {} fn p1(v: T) -> Box where T : X diff --git a/src/test/compile-fail/regions-infer-contravariance-due-to-decl.rs b/src/test/compile-fail/regions-infer-contravariance-due-to-decl.rs index 6c5e90a54de..b7ef19d1e3b 100644 --- a/src/test/compile-fail/regions-infer-contravariance-due-to-decl.rs +++ b/src/test/compile-fail/regions-infer-contravariance-due-to-decl.rs @@ -20,7 +20,7 @@ use std::marker; // Contravariant<'foo> <: Contravariant<'static> because // 'foo <= 'static struct Contravariant<'a> { - marker: marker::ContravariantLifetime<'a> + marker: marker::PhantomData<&'a()> } fn use_<'short,'long>(c: Contravariant<'short>, diff --git a/src/test/compile-fail/regions-infer-covariance-due-to-decl.rs b/src/test/compile-fail/regions-infer-covariance-due-to-decl.rs index d8e31fa1374..0d3d9dacbd6 100644 --- a/src/test/compile-fail/regions-infer-covariance-due-to-decl.rs +++ b/src/test/compile-fail/regions-infer-covariance-due-to-decl.rs @@ -17,7 +17,7 @@ use std::marker; struct Covariant<'a> { - marker: marker::CovariantLifetime<'a> + marker: marker::PhantomData } fn use_<'short,'long>(c: Covariant<'long>, diff --git a/src/test/compile-fail/regions-infer-invariance-due-to-decl.rs b/src/test/compile-fail/regions-infer-invariance-due-to-decl.rs index e88c96de9e4..8c191fbd5bb 100644 --- a/src/test/compile-fail/regions-infer-invariance-due-to-decl.rs +++ b/src/test/compile-fail/regions-infer-invariance-due-to-decl.rs @@ -11,7 +11,7 @@ use std::marker; struct invariant<'a> { - marker: marker::InvariantLifetime<'a> + marker: marker::PhantomData<*mut &'a()> } fn to_same_lifetime<'r>(b_isize: invariant<'r>) { diff --git a/src/test/compile-fail/required-lang-item.rs b/src/test/compile-fail/required-lang-item.rs index 7d252604883..1b749faf1b8 100644 --- a/src/test/compile-fail/required-lang-item.rs +++ b/src/test/compile-fail/required-lang-item.rs @@ -11,7 +11,11 @@ #![feature(lang_items, no_std)] #![no_std] -#[lang="sized"] pub trait Sized {} +#[lang="phantom_fn"] +pub trait PhantomFn { } +impl PhantomFn for U { } + +#[lang="sized"] pub trait Sized : PhantomFn {} // error-pattern:requires `start` lang_item diff --git a/src/test/compile-fail/shadowed-type-parameter.rs b/src/test/compile-fail/shadowed-type-parameter.rs index 1a3d7821159..1f72db1e894 100644 --- a/src/test/compile-fail/shadowed-type-parameter.rs +++ b/src/test/compile-fail/shadowed-type-parameter.rs @@ -12,19 +12,21 @@ #![feature(box_syntax)] -struct Foo; +struct Foo(T); impl Foo { fn shadow_in_method(&self) {} //~^ ERROR type parameter `T` shadows another type parameter fn not_shadow_in_item(&self) { - struct Bar; // not a shadow, separate item + struct Bar(T,U); // not a shadow, separate item fn foo() {} // same } } trait Bar { + fn dummy(&self) -> T; + fn shadow_in_required(&self); //~^ ERROR type parameter `T` shadows another type parameter diff --git a/src/test/compile-fail/slightly-nice-generic-literal-messages.rs b/src/test/compile-fail/slightly-nice-generic-literal-messages.rs index 1203d622348..3c1c3796a24 100644 --- a/src/test/compile-fail/slightly-nice-generic-literal-messages.rs +++ b/src/test/compile-fail/slightly-nice-generic-literal-messages.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Foo(T); +use std::marker; + +struct Foo(T, marker::PhantomData); fn main() { - match Foo(1.1) { + match Foo(1.1, marker::PhantomData) { 1 => {} //~^ ERROR mismatched types //~| expected `Foo<_, _>` diff --git a/src/test/compile-fail/staticness-mismatch.rs b/src/test/compile-fail/staticness-mismatch.rs index bf4e46cace3..2dfc9b79ee2 100644 --- a/src/test/compile-fail/staticness-mismatch.rs +++ b/src/test/compile-fail/staticness-mismatch.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - trait foo { + fn dummy(&self) { } fn bar(); } diff --git a/src/test/compile-fail/trait-as-struct-constructor.rs b/src/test/compile-fail/trait-as-struct-constructor.rs index a1fcab002e1..fff14414094 100644 --- a/src/test/compile-fail/trait-as-struct-constructor.rs +++ b/src/test/compile-fail/trait-as-struct-constructor.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait TraitNotAStruct { } +trait TraitNotAStruct : ::std::marker::MarkerTrait { } fn main() { TraitNotAStruct{ value: 0 }; diff --git a/src/test/compile-fail/trait-bounds-cant-coerce.rs b/src/test/compile-fail/trait-bounds-cant-coerce.rs index 79174552ae0..3129dceffbb 100644 --- a/src/test/compile-fail/trait-bounds-cant-coerce.rs +++ b/src/test/compile-fail/trait-bounds-cant-coerce.rs @@ -10,6 +10,7 @@ trait Foo { + fn dummy(&self) { } } fn a(_x: Box) { diff --git a/src/test/compile-fail/trait-bounds-impl-comparison-1.rs b/src/test/compile-fail/trait-bounds-impl-comparison-1.rs index 477bd4f5be9..34e06cc9365 100644 --- a/src/test/compile-fail/trait-bounds-impl-comparison-1.rs +++ b/src/test/compile-fail/trait-bounds-impl-comparison-1.rs @@ -11,7 +11,10 @@ // Make sure rustc checks the type parameter bounds in implementations of traits, // see #2687 -trait A {} +use std::marker; + +trait A : marker::PhantomFn { +} trait B: A {} @@ -62,15 +65,16 @@ impl Foo for isize { //~^ ERROR the requirement `T : C` appears on the impl } - -trait Getter { } +trait Getter { + fn get(&self) -> T { loop { } } +} trait Trait { - fn method>(); + fn method>(&self); } impl Trait for usize { - fn method>() {} + fn method>(&self) {} //~^ G : Getter` appears on the impl method but not on the corresponding trait method } diff --git a/src/test/compile-fail/trait-bounds-impl-comparison-2.rs b/src/test/compile-fail/trait-bounds-impl-comparison-2.rs index 8ad19116e7b..284c4fac953 100644 --- a/src/test/compile-fail/trait-bounds-impl-comparison-2.rs +++ b/src/test/compile-fail/trait-bounds-impl-comparison-2.rs @@ -14,7 +14,9 @@ trait Iterator { fn next(&mut self) -> Option; } -trait IteratorUtil { +trait IteratorUtil + : ::std::marker::PhantomFn<(),A> +{ fn zip>(self, other: U) -> ZipIterator; } diff --git a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs index 434d803d718..448b186f6a5 100644 --- a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs +++ b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs @@ -9,6 +9,7 @@ // except according to those terms. trait Foo { + fn dummy(&self) { } } // This should emit the less confusing error, not the more confusing one. diff --git a/src/test/compile-fail/trait-bounds-on-structs-and-enums-locals.rs b/src/test/compile-fail/trait-bounds-on-structs-and-enums-locals.rs index 118dfeb37c2..df44e847c50 100644 --- a/src/test/compile-fail/trait-bounds-on-structs-and-enums-locals.rs +++ b/src/test/compile-fail/trait-bounds-on-structs-and-enums-locals.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Trait {} +trait Trait { + fn dummy(&self) { } +} struct Foo { x: T, diff --git a/src/test/compile-fail/trait-bounds-on-structs-and-enums-static.rs b/src/test/compile-fail/trait-bounds-on-structs-and-enums-static.rs index d5369817e9a..18871d0d386 100644 --- a/src/test/compile-fail/trait-bounds-on-structs-and-enums-static.rs +++ b/src/test/compile-fail/trait-bounds-on-structs-and-enums-static.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Trait {} +trait Trait { + fn dummy(&self) { } +} struct Foo { x: T, diff --git a/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs b/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs index 490ee0e8ad6..8dfdb2f205d 100644 --- a/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs +++ b/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Trait {} +use std::marker::MarkerTrait; + +trait Trait : MarkerTrait {} struct Foo { x: T, @@ -51,15 +53,15 @@ enum MoreBadness { EvenMoreBadness(Bar), } -trait PolyTrait { - fn whatever() {} +trait PolyTrait +{ + fn whatever(&self, t: T) {} } struct Struct; impl PolyTrait> for Struct { //~^ ERROR not implemented - fn whatever() {} } fn main() { diff --git a/src/test/compile-fail/trait-bounds-sugar.rs b/src/test/compile-fail/trait-bounds-sugar.rs index 3d264e681a3..e4058a0943a 100644 --- a/src/test/compile-fail/trait-bounds-sugar.rs +++ b/src/test/compile-fail/trait-bounds-sugar.rs @@ -10,8 +10,9 @@ // Tests for "default" bounds inferred for traits with no bounds list. +use std::marker::MarkerTrait; -trait Foo {} +trait Foo : MarkerTrait {} fn a(_x: Box) { } diff --git a/src/test/compile-fail/trait-impl-1.rs b/src/test/compile-fail/trait-impl-1.rs index dadcbd5bce7..2f4793b4d88 100644 --- a/src/test/compile-fail/trait-impl-1.rs +++ b/src/test/compile-fail/trait-impl-1.rs @@ -12,7 +12,9 @@ // trait impl is only applied to a trait object, not concrete types which implement // the trait. -trait T {} +use std::marker::MarkerTrait; + +trait T : MarkerTrait {} impl<'a> T+'a { fn foo(&self) {} diff --git a/src/test/compile-fail/trait-object-safety.rs b/src/test/compile-fail/trait-object-safety.rs index 761bcd4968a..d45d13556e1 100644 --- a/src/test/compile-fail/trait-object-safety.rs +++ b/src/test/compile-fail/trait-object-safety.rs @@ -12,6 +12,7 @@ trait Tr { fn foo(); + fn bar(&self) { } } struct St; diff --git a/src/test/compile-fail/trait-static-method-generic-inference.rs b/src/test/compile-fail/trait-static-method-generic-inference.rs index 651f663fc99..0e357d9d4d5 100644 --- a/src/test/compile-fail/trait-static-method-generic-inference.rs +++ b/src/test/compile-fail/trait-static-method-generic-inference.rs @@ -16,6 +16,7 @@ mod base { pub trait HasNew { fn new() -> T; + fn dummy(&self) { } } pub struct Foo { diff --git a/src/test/compile-fail/typeck-negative-impls-builtin.rs b/src/test/compile-fail/typeck-negative-impls-builtin.rs index 9da79b11cf0..557fb2f4f88 100644 --- a/src/test/compile-fail/typeck-negative-impls-builtin.rs +++ b/src/test/compile-fail/typeck-negative-impls-builtin.rs @@ -12,7 +12,9 @@ struct TestType; -trait TestTrait {} +trait TestTrait { + fn dummy(&self) { } +} impl !TestTrait for TestType {} //~^ ERROR negative impls are currently allowed just for `Send` and `Sync` diff --git a/src/test/compile-fail/typeck_type_placeholder_mismatch.rs b/src/test/compile-fail/typeck_type_placeholder_mismatch.rs index a34be63ba6b..1daea8f915b 100644 --- a/src/test/compile-fail/typeck_type_placeholder_mismatch.rs +++ b/src/test/compile-fail/typeck_type_placeholder_mismatch.rs @@ -11,14 +11,16 @@ // This test checks that genuine type errors with partial // type hints are understandable. -struct Foo; -struct Bar; +use std::marker::PhantomData; + +struct Foo(PhantomData); +struct Bar(PhantomData); pub fn main() { } fn test1() { - let x: Foo<_> = Bar::; + let x: Foo<_> = Bar::(PhantomData); //~^ ERROR mismatched types //~| expected `Foo<_>` //~| found `Bar` @@ -28,7 +30,7 @@ fn test1() { } fn test2() { - let x: Foo<_> = Bar::; + let x: Foo<_> = Bar::(PhantomData); //~^ ERROR mismatched types //~| expected `Foo<_>` //~| found `Bar` diff --git a/src/test/compile-fail/unboxed-closure-feature-gate.rs b/src/test/compile-fail/unboxed-closure-feature-gate.rs index 3536244f011..74a6f869f63 100644 --- a/src/test/compile-fail/unboxed-closure-feature-gate.rs +++ b/src/test/compile-fail/unboxed-closure-feature-gate.rs @@ -11,8 +11,12 @@ // Check that parenthetical notation is feature-gated except with the // `Fn` traits. +use std::marker; + trait Foo { type Output; + + fn dummy(&self, a: A) { } } fn main() { diff --git a/src/test/compile-fail/unboxed-closure-sugar-default.rs b/src/test/compile-fail/unboxed-closure-sugar-default.rs index 870377bc1ad..831db98941c 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-default.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-default.rs @@ -19,7 +19,7 @@ trait Foo { fn dummy(&self, t: T, v: V); } -trait Eq { } +trait Eq { fn same_types(&self, x: &X) -> bool { true } } impl Eq for X { } fn eq() where A : Eq { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs index dc5576aee65..6d315c1b7a9 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs @@ -16,12 +16,14 @@ #![feature(unboxed_closures)] #![allow(dead_code)] +use std::marker::PhantomFn; + trait Foo { type Output; fn dummy(&self, t: T, u: Self::Output); } -trait Eq { } +trait Eq : PhantomFn<(Self,X)> { } impl Eq for X { } fn eq>() { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs b/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs index d2f781bba11..bd3530e6e30 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs @@ -16,12 +16,14 @@ #![feature(unboxed_closures)] #![allow(dead_code)] +use std::marker; + trait Foo { type Output; fn dummy(&self, t: T); } -trait Eq { } +trait Eq : marker::PhantomFn<(Self, X)> { } impl Eq for X { } fn eq>() { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-region.rs b/src/test/compile-fail/unboxed-closure-sugar-region.rs index 75688e44e80..057b496bd43 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-region.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-region.rs @@ -22,7 +22,7 @@ trait Foo<'a,T> { fn dummy(&'a self) -> &'a (T,Self::Output); } -trait Eq { } +trait Eq { fn is_of_eq_type(&self, x: &X) -> bool { true } } impl Eq for X { } fn eq>() { } diff --git a/src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs b/src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs index 215b2c6798e..713b64b1349 100644 --- a/src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs +++ b/src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs @@ -10,7 +10,7 @@ #![feature(core,unboxed_closures)] -use std::marker::CovariantType; +use std::marker::PhantomData; // A erroneous variant of `run-pass/unboxed_closures-infer-recursive-fn.rs` // where we attempt to perform mutation in the recursive function. This fails to compile @@ -18,12 +18,12 @@ use std::marker::CovariantType; struct YCombinator { func: F, - marker: CovariantType<(A,R)>, + marker: PhantomData<(A,R)>, } impl YCombinator { fn new(f: F) -> YCombinator { - YCombinator { func: f, marker: CovariantType } + YCombinator { func: f, marker: PhantomData } } } diff --git a/src/test/compile-fail/unnecessary-private.rs b/src/test/compile-fail/unnecessary-private.rs index e3707292f24..964db6e9a45 100644 --- a/src/test/compile-fail/unnecessary-private.rs +++ b/src/test/compile-fail/unnecessary-private.rs @@ -13,10 +13,10 @@ fn main() { pub struct A; //~ ERROR: visibility has no effect pub enum B {} //~ ERROR: visibility has no effect pub trait C { //~ ERROR: visibility has no effect - pub fn foo() {} //~ ERROR: visibility has no effect + pub fn foo(&self) {} //~ ERROR: visibility has no effect } impl A { - pub fn foo() {} //~ ERROR: visibility has no effect + pub fn foo(&self) {} //~ ERROR: visibility has no effect } struct D { diff --git a/src/test/compile-fail/unsized-inherent-impl-self-type.rs b/src/test/compile-fail/unsized-inherent-impl-self-type.rs index 8740346a217..a03c76b12dd 100644 --- a/src/test/compile-fail/unsized-inherent-impl-self-type.rs +++ b/src/test/compile-fail/unsized-inherent-impl-self-type.rs @@ -12,7 +12,7 @@ // impl - struct -struct S5; +struct S5(Y); impl S5 { //~ ERROR not implemented } diff --git a/src/test/compile-fail/unsized-trait-impl-self-type.rs b/src/test/compile-fail/unsized-trait-impl-self-type.rs index 3dd55b0ba7d..08df1d9b7b8 100644 --- a/src/test/compile-fail/unsized-trait-impl-self-type.rs +++ b/src/test/compile-fail/unsized-trait-impl-self-type.rs @@ -12,9 +12,10 @@ // impl - struct trait T3 { + fn foo(&self, z: &Z); } -struct S5; +struct S5(Y); impl T3 for S5 { //~ ERROR not implemented } diff --git a/src/test/compile-fail/unsized-trait-impl-trait-arg.rs b/src/test/compile-fail/unsized-trait-impl-trait-arg.rs index ac8043d6852..4723dfeaeb9 100644 --- a/src/test/compile-fail/unsized-trait-impl-trait-arg.rs +++ b/src/test/compile-fail/unsized-trait-impl-trait-arg.rs @@ -12,8 +12,9 @@ // impl - unbounded trait T2 { + fn foo(&self, z: Z); } -struct S4; +struct S4(Box); impl T2 for S4 { //~^ ERROR `core::marker::Sized` is not implemented for the type `X` } diff --git a/src/test/compile-fail/unsized3.rs b/src/test/compile-fail/unsized3.rs index 4fc76c99c60..de1cbab82b2 100644 --- a/src/test/compile-fail/unsized3.rs +++ b/src/test/compile-fail/unsized3.rs @@ -10,6 +10,7 @@ // Test sized-ness checking in substitution within fn bodies.. +use std::marker; // Unbounded. fn f1(x: &X) { @@ -20,7 +21,9 @@ fn f2(x: &X) { } // Bounded. -trait T {} +trait T { + fn foo(&self) { } +} fn f3(x: &X) { f4::(x); //~^ ERROR the trait `core::marker::Sized` is not implemented diff --git a/src/test/compile-fail/unsized6.rs b/src/test/compile-fail/unsized6.rs index 217d1f44d84..f31a6ffdc0d 100644 --- a/src/test/compile-fail/unsized6.rs +++ b/src/test/compile-fail/unsized6.rs @@ -10,8 +10,9 @@ // Test `?Sized` local variables. +use std::marker; -trait T {} +trait T : marker::MarkerTrait { } fn f1(x: &X) { let _: X; // <-- this is OK, no bindings created, no initializer. diff --git a/src/test/compile-fail/unsized7.rs b/src/test/compile-fail/unsized7.rs index 6fc547c0b8e..6ea3d0720ee 100644 --- a/src/test/compile-fail/unsized7.rs +++ b/src/test/compile-fail/unsized7.rs @@ -10,13 +10,17 @@ // Test sized-ness checking in substitution in impls. -trait T {} +use std::marker::MarkerTrait; + +trait T : MarkerTrait {} // I would like these to fail eventually. // impl - bounded trait T1 { + fn dummy(&self) -> Z; } -struct S3; + +struct S3(Box); impl T1 for S3 { //~^ ERROR `core::marker::Sized` is not implemented for the type `X` } diff --git a/src/test/compile-fail/unused-attr.rs b/src/test/compile-fail/unused-attr.rs index 2d4bc0c857a..af242b96a84 100644 --- a/src/test/compile-fail/unused-attr.rs +++ b/src/test/compile-fail/unused-attr.rs @@ -52,9 +52,9 @@ struct Foo { #[foo] //~ ERROR unused attribute trait Baz { #[foo] //~ ERROR unused attribute - fn blah(); + fn blah(&self); #[foo] //~ ERROR unused attribute - fn blah2() {} + fn blah2(&self) {} } fn main() {} diff --git a/src/test/compile-fail/useless-priv.rs b/src/test/compile-fail/useless-priv.rs index d8531f4543d..b1120e54434 100644 --- a/src/test/compile-fail/useless-priv.rs +++ b/src/test/compile-fail/useless-priv.rs @@ -12,12 +12,14 @@ struct A { pub i: isize } pub enum C { pub Variant } //~ ERROR: unnecessary `pub` pub trait E { - pub fn foo() {} //~ ERROR: unnecessary visibility + pub fn foo(&self) {} //~ ERROR: unnecessary visibility +} +trait F { + pub fn foo(&self) {} //~ ERROR: unnecessary visibility } -trait F { pub fn foo() {} } //~ ERROR: unnecessary visibility impl E for A { - pub fn foo() {} //~ ERROR: unnecessary visibility + pub fn foo(&self) {} //~ ERROR: unnecessary visibility } fn main() {} diff --git a/src/test/compile-fail/useless-priv2.rs b/src/test/compile-fail/useless-priv2.rs index 7125a66b294..a404d09248f 100644 --- a/src/test/compile-fail/useless-priv2.rs +++ b/src/test/compile-fail/useless-priv2.rs @@ -9,8 +9,10 @@ // except according to those terms. pub trait E { - pub fn foo(); //~ ERROR: unnecessary visibility + pub fn foo(&self); //~ ERROR: unnecessary visibility +} +trait F { + pub fn foo(&self); //~ ERROR: unnecessary visibility } -trait F { pub fn foo(); } //~ ERROR: unnecessary visibility fn main() {} diff --git a/src/test/compile-fail/variance-contravariant-arg-object.rs b/src/test/compile-fail/variance-contravariant-arg-object.rs new file mode 100644 index 00000000000..3330e1d0d51 --- /dev/null +++ b/src/test/compile-fail/variance-contravariant-arg-object.rs @@ -0,0 +1,31 @@ +// 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. + +#![allow(dead_code)] + +trait Get : 'static { + fn get(&self, t: T); +} + +fn get_min_from_max<'min, 'max>(v: Box>) + -> Box> + where 'max : 'min +{ + v //~ ERROR mismatched types +} + +fn get_max_from_min<'min, 'max, G>(v: Box>) + -> Box> + where 'max : 'min +{ + v +} + +fn main() { } diff --git a/src/test/compile-fail/variance-contravariant-arg-trait-match.rs b/src/test/compile-fail/variance-contravariant-arg-trait-match.rs new file mode 100644 index 00000000000..caaad4014ad --- /dev/null +++ b/src/test/compile-fail/variance-contravariant-arg-trait-match.rs @@ -0,0 +1,31 @@ +// 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. + +#![allow(dead_code)] + +trait Get { + fn get(&self, t: T); +} + +fn get_min_from_max<'min, 'max, G>() + where 'max : 'min, G : Get<&'max i32> +{ + impls_get::() //~ ERROR mismatched types +} + +fn get_max_from_min<'min, 'max, G>() + where 'max : 'min, G : Get<&'min i32> +{ + impls_get::() +} + +fn impls_get() where G : Get { } + +fn main() { } diff --git a/src/test/compile-fail/variance-contravariant-self-trait-match.rs b/src/test/compile-fail/variance-contravariant-self-trait-match.rs new file mode 100644 index 00000000000..013511ed517 --- /dev/null +++ b/src/test/compile-fail/variance-contravariant-self-trait-match.rs @@ -0,0 +1,31 @@ +// 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. + +#![allow(dead_code)] + +trait Get { + fn get(&self); +} + +fn get_min_from_max<'min, 'max, G>() + where 'max : 'min, G : 'max, &'max G : Get +{ + impls_get::<&'min G>(); //~ ERROR mismatched types +} + +fn get_max_from_min<'min, 'max, G>() + where 'max : 'min, G : 'max, &'min G : Get +{ + impls_get::<&'max G>(); +} + +fn impls_get() where G : Get { } + +fn main() { } diff --git a/src/test/compile-fail/variance-covariant-arg-object.rs b/src/test/compile-fail/variance-covariant-arg-object.rs new file mode 100644 index 00000000000..828c987c082 --- /dev/null +++ b/src/test/compile-fail/variance-covariant-arg-object.rs @@ -0,0 +1,31 @@ +// 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. + +#![allow(dead_code)] + +trait Get : 'static { + fn get(&self) -> T; +} + +fn get_min_from_max<'min, 'max>(v: Box>) + -> Box> + where 'max : 'min +{ + v +} + +fn get_max_from_min<'min, 'max, G>(v: Box>) + -> Box> + where 'max : 'min +{ + v //~ ERROR mismatched types +} + +fn main() { } diff --git a/src/test/compile-fail/variance-covariant-arg-trait-match.rs b/src/test/compile-fail/variance-covariant-arg-trait-match.rs new file mode 100644 index 00000000000..17761b9c0b1 --- /dev/null +++ b/src/test/compile-fail/variance-covariant-arg-trait-match.rs @@ -0,0 +1,31 @@ +// 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. + +#![allow(dead_code)] + +trait Get { + fn get(&self) -> T; +} + +fn get_min_from_max<'min, 'max, G>() + where 'max : 'min, G : Get<&'max i32> +{ + impls_get::() +} + +fn get_max_from_min<'min, 'max, G>() + where 'max : 'min, G : Get<&'min i32> +{ + impls_get::() //~ ERROR mismatched types +} + +fn impls_get() where G : Get { } + +fn main() { } diff --git a/src/test/compile-fail/variance-covariant-self-trait-match.rs b/src/test/compile-fail/variance-covariant-self-trait-match.rs new file mode 100644 index 00000000000..4e94a3eeb46 --- /dev/null +++ b/src/test/compile-fail/variance-covariant-self-trait-match.rs @@ -0,0 +1,31 @@ +// 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. + +#![allow(dead_code)] + +trait Get { + fn get() -> Self; +} + +fn get_min_from_max<'min, 'max, G>() + where 'max : 'min, G : 'max, &'max G : Get +{ + impls_get::<&'min G>(); +} + +fn get_max_from_min<'min, 'max, G>() + where 'max : 'min, G : 'max, &'min G : Get +{ + impls_get::<&'max G>(); //~ ERROR mismatched types +} + +fn impls_get() where G : Get { } + +fn main() { } diff --git a/src/test/compile-fail/variance-deprecated-markers.rs b/src/test/compile-fail/variance-deprecated-markers.rs new file mode 100644 index 00000000000..8f9d24cb132 --- /dev/null +++ b/src/test/compile-fail/variance-deprecated-markers.rs @@ -0,0 +1,35 @@ +// 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. + +// Test that the deprecated markers still have their old effect. + +#![feature(rustc_attrs)] + +use std::marker; + +#[rustc_variance] +struct A(marker::CovariantType); //~ ERROR types=[[+];[];[]] + +#[rustc_variance] +struct B(marker::ContravariantType); //~ ERROR types=[[-];[];[]] + +#[rustc_variance] +struct C(marker::InvariantType); //~ ERROR types=[[o];[];[]] + +#[rustc_variance] +struct D<'a>(marker::CovariantLifetime<'a>); //~ ERROR regions=[[+];[];[]] + +#[rustc_variance] +struct E<'a>(marker::ContravariantLifetime<'a>); //~ ERROR regions=[[-];[];[]] + +#[rustc_variance] +struct F<'a>(marker::InvariantLifetime<'a>); //~ ERROR regions=[[o];[];[]] + +fn main() { } diff --git a/src/test/compile-fail/variance-invariant-arg-object.rs b/src/test/compile-fail/variance-invariant-arg-object.rs new file mode 100644 index 00000000000..9edb510b826 --- /dev/null +++ b/src/test/compile-fail/variance-invariant-arg-object.rs @@ -0,0 +1,31 @@ +// 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. + +#![allow(dead_code)] + +trait Get : 'static { + fn get(&self, t: T) -> T; +} + +fn get_min_from_max<'min, 'max>(v: Box>) + -> Box> + where 'max : 'min +{ + v //~ ERROR mismatched types +} + +fn get_max_from_min<'min, 'max, G>(v: Box>) + -> Box> + where 'max : 'min +{ + v //~ ERROR mismatched types +} + +fn main() { } diff --git a/src/test/compile-fail/variance-invariant-arg-trait-match.rs b/src/test/compile-fail/variance-invariant-arg-trait-match.rs new file mode 100644 index 00000000000..45fed0b083d --- /dev/null +++ b/src/test/compile-fail/variance-invariant-arg-trait-match.rs @@ -0,0 +1,31 @@ +// 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. + +#![allow(dead_code)] + +trait Get { + fn get(&self, t: T) -> T; +} + +fn get_min_from_max<'min, 'max, G>() + where 'max : 'min, G : Get<&'max i32> +{ + impls_get::() //~ ERROR mismatched types +} + +fn get_max_from_min<'min, 'max, G>() + where 'max : 'min, G : Get<&'min i32> +{ + impls_get::() //~ ERROR mismatched types +} + +fn impls_get() where G : Get { } + +fn main() { } diff --git a/src/test/compile-fail/variance-invariant-self-trait-match.rs b/src/test/compile-fail/variance-invariant-self-trait-match.rs new file mode 100644 index 00000000000..b46cd302ae5 --- /dev/null +++ b/src/test/compile-fail/variance-invariant-self-trait-match.rs @@ -0,0 +1,31 @@ +// 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. + +#![allow(dead_code)] + +trait Get { + fn get(&self) -> Self; +} + +fn get_min_from_max<'min, 'max, G>() + where 'max : 'min, &'max G : Get +{ + impls_get::<&'min G>(); //~ ERROR mismatched types +} + +fn get_max_from_min<'min, 'max, G>() + where 'max : 'min, &'min G : Get +{ + impls_get::<&'max G>(); //~ ERROR mismatched types +} + +fn impls_get() where G : Get { } + +fn main() { } diff --git a/src/test/compile-fail/variance-issue-20533.rs b/src/test/compile-fail/variance-issue-20533.rs new file mode 100644 index 00000000000..0254f56bd1a --- /dev/null +++ b/src/test/compile-fail/variance-issue-20533.rs @@ -0,0 +1,54 @@ +// 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. + +// Regression test for issue #20533. At some point, only 1 out of the +// 3 errors below were being reported. + +use std::marker::PhantomData; + +fn foo<'a, T>(_x: &'a T) -> PhantomData<&'a ()> { + PhantomData +} + +struct Wrap(T); + +fn bar<'a, T>(_x: &'a T) -> Wrap> { + Wrap(PhantomData) +} + +struct Baked<'a>(PhantomData<&'a ()>); + +fn baz<'a, T>(_x: &'a T) -> Baked<'a> { + Baked(PhantomData) +} + +struct AffineU32(u32); + +fn main() { + { + let a = AffineU32(1_u32); + let x = foo(&a); + drop(a); //~ ERROR cannot move out of `a` + drop(x); + } + { + let a = AffineU32(1_u32); + let x = bar(&a); + drop(a); //~ ERROR cannot move out of `a` + drop(x); + } + { + let a = AffineU32(1_u32); + let x = baz(&a); + drop(a); //~ ERROR cannot move out of `a` + drop(x); + } +} + diff --git a/src/test/compile-fail/variance-regions-direct.rs b/src/test/compile-fail/variance-regions-direct.rs index d70305d1106..da4d6c75227 100644 --- a/src/test/compile-fail/variance-regions-direct.rs +++ b/src/test/compile-fail/variance-regions-direct.rs @@ -60,6 +60,7 @@ struct Test6<'a, 'b> { //~ ERROR regions=[[-, o];[];[]] #[rustc_variance] struct Test7<'a> { //~ ERROR regions=[[*];[];[]] + //~^ ERROR parameter `'a` is never used x: isize } diff --git a/src/test/compile-fail/variance-regions-indirect.rs b/src/test/compile-fail/variance-regions-indirect.rs index 4bb329d6304..9beb90d0b24 100644 --- a/src/test/compile-fail/variance-regions-indirect.rs +++ b/src/test/compile-fail/variance-regions-indirect.rs @@ -16,6 +16,7 @@ #[rustc_variance] enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[]] + //~^ ERROR parameter `'d` is never used Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), Test8C(&'b mut &'c str), @@ -23,16 +24,19 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[]] #[rustc_variance] struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[];[]] + //~^ ERROR parameter `'w` is never used f: Base<'z, 'y, 'x, 'w> } #[rustc_variance] // Combine - and + to yield o struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[];[]] + //~^ ERROR parameter `'c` is never used f: Base<'a, 'a, 'b, 'c> } #[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here) struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[];[]] + //~^ ERROR parameter `'c` is never used f: Base<'a, 'b, 'a, 'c> } diff --git a/src/test/run-pass/regions-infer-bivariance.rs b/src/test/compile-fail/variance-regions-unused-direct.rs similarity index 55% rename from src/test/run-pass/regions-infer-bivariance.rs rename to src/test/compile-fail/variance-regions-unused-direct.rs index a3288e2e1b9..396e7765206 100644 --- a/src/test/run-pass/regions-infer-bivariance.rs +++ b/src/test/compile-fail/variance-regions-unused-direct.rs @@ -8,21 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that a type whose lifetime parameters is never used is -// inferred to be bivariant. +// Test that disallow lifetime parameters that are unused. use std::marker; -struct Bivariant<'a>; +struct Bivariant<'a>; //~ ERROR parameter `'a` is never used -fn use1<'short,'long>(c: Bivariant<'short>, - _where:Option<&'short &'long ()>) { - let _: Bivariant<'long> = c; +struct Struct<'a, 'd> { //~ ERROR parameter `'d` is never used + field: &'a [i32] } -fn use2<'short,'long>(c: Bivariant<'long>, - _where:Option<&'short &'long ()>) { - let _: Bivariant<'short> = c; +trait Trait<'a, 'd> { //~ ERROR parameter `'d` is never used + fn method(&'a self); } -pub fn main() {} +fn main() {} diff --git a/src/test/run-pass/export-non-interference.rs b/src/test/compile-fail/variance-regions-unused-indirect.rs similarity index 67% rename from src/test/run-pass/export-non-interference.rs rename to src/test/compile-fail/variance-regions-unused-indirect.rs index 94652e30fe6..2d234ed7b57 100644 --- a/src/test/run-pass/export-non-interference.rs +++ b/src/test/compile-fail/variance-regions-unused-indirect.rs @@ -8,7 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Test that disallow lifetime parameters that are unused. -enum list_cell { cons(Box>), nil } +enum Foo<'a> { //~ ERROR parameter `'a` is never used + Foo1(Bar<'a>) +} -pub fn main() { } +enum Bar<'a> { //~ ERROR parameter `'a` is never used + Bar1(Foo<'a>) +} + +fn main() {} diff --git a/src/test/compile-fail/variance-trait-bounds.rs b/src/test/compile-fail/variance-trait-bounds.rs new file mode 100644 index 00000000000..88b50058b65 --- /dev/null +++ b/src/test/compile-fail/variance-trait-bounds.rs @@ -0,0 +1,65 @@ +// 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. + +#![deny(bivariance)] +#![allow(dead_code)] +#![feature(rustc_attrs)] + +// Check that bounds on type parameters (other than `Self`) do not +// influence variance. + +#[rustc_variance] +trait Getter { //~ ERROR types=[[+];[-];[]] + fn get(&self) -> T; +} + +#[rustc_variance] +trait Setter { //~ ERROR types=[[-];[-];[]] + fn get(&self, T); +} + +#[rustc_variance] +struct TestStruct> { //~ ERROR types=[[+, +];[];[]] + t: T, u: U +} + +#[rustc_variance] +enum TestEnum> {//~ ERROR types=[[*, +];[];[]] + //~^ ERROR parameter `U` is never used + Foo(T) +} + +#[rustc_variance] +trait TestTrait> { //~ ERROR types=[[-, +];[-];[]] + fn getter(&self, u: U) -> T; +} + +#[rustc_variance] +trait TestTrait2 : Getter { //~ ERROR types=[[+];[-];[]] +} + +#[rustc_variance] +trait TestTrait3 { //~ ERROR types=[[-];[-];[]] + fn getter>(&self); +} + +#[rustc_variance] +struct TestContraStruct> { //~ ERROR types=[[*, +];[];[]] + //~^ ERROR parameter `U` is never used + t: T +} + +#[rustc_variance] +struct TestBox+Setter> { //~ ERROR types=[[*, +];[];[]] + //~^ ERROR parameter `U` is never used + t: T +} + +pub fn main() { } diff --git a/src/test/compile-fail/variance-trait-object-bound.rs b/src/test/compile-fail/variance-trait-object-bound.rs index 965b9430a5e..f0ca1edd563 100644 --- a/src/test/compile-fail/variance-trait-object-bound.rs +++ b/src/test/compile-fail/variance-trait-object-bound.rs @@ -18,7 +18,7 @@ use std::mem; -trait T { fn foo(); } +trait T { fn foo(&self); } #[rustc_variance] struct TOption<'a> { //~ ERROR regions=[[-];[];[]] diff --git a/src/test/compile-fail/variance-types-bounds.rs b/src/test/compile-fail/variance-types-bounds.rs new file mode 100644 index 00000000000..d53e4cd7610 --- /dev/null +++ b/src/test/compile-fail/variance-types-bounds.rs @@ -0,0 +1,76 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we correctly infer variance for type parameters in +// various types and traits. + +#![feature(rustc_attrs)] + +#[rustc_variance] +struct TestImm { //~ ERROR types=[[+, +];[];[]] + x: A, + y: B, +} + +#[rustc_variance] +struct TestMut { //~ ERROR types=[[+, o];[];[]] + x: A, + y: &'static mut B, +} + +#[rustc_variance] +struct TestIndirect { //~ ERROR types=[[+, o];[];[]] + m: TestMut +} + +#[rustc_variance] +struct TestIndirect2 { //~ ERROR types=[[o, o];[];[]] + n: TestMut, + m: TestMut +} + +#[rustc_variance] +trait Getter { //~ ERROR types=[[+];[-];[]] + fn get(&self) -> A; +} + +#[rustc_variance] +trait Setter { //~ ERROR types=[[-];[o];[]] + fn set(&mut self, a: A); +} + +#[rustc_variance] +trait GetterSetter { //~ ERROR types=[[o];[o];[]] + fn get(&self) -> A; + fn set(&mut self, a: A); +} + +#[rustc_variance] +trait GetterInTypeBound { //~ ERROR types=[[-];[-];[]] + // Here, the use of `A` in the method bound *does* affect + // variance. Think of it as if the method requested a dictionary + // for `T:Getter`. Since this dictionary is an input, it is + // contravariant, and the Getter is covariant w/r/t A, yielding an + // overall contravariant result. + fn do_it>(&self); +} + +#[rustc_variance] +trait SetterInTypeBound { //~ ERROR types=[[+];[-];[]] + fn do_it>(&self); +} + +#[rustc_variance] +struct TestObject { //~ ERROR types=[[-, +];[];[]] + n: Box+Send>, + m: Box+Send>, +} + +fn main() {} diff --git a/src/test/compile-fail/variance-types.rs b/src/test/compile-fail/variance-types.rs new file mode 100644 index 00000000000..e407ebe345a --- /dev/null +++ b/src/test/compile-fail/variance-types.rs @@ -0,0 +1,52 @@ +// 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. + +#![deny(bivariance)] +#![allow(dead_code)] +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Check that a type parameter which is only used in a trait bound is +// not considered bivariant. + +#[rustc_variance] +struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[[o, o];[];[]], regions=[[-];[];[]] + t: &'a mut (A,B) +} + +#[rustc_variance] +struct InvariantCell { //~ ERROR types=[[o];[];[]] + t: Cell +} + +#[rustc_variance] +struct InvariantIndirect { //~ ERROR types=[[o];[];[]] + t: InvariantCell +} + +#[rustc_variance] +struct Covariant { //~ ERROR types=[[+];[];[]] + t: A, u: fn() -> A +} + +#[rustc_variance] +struct Contravariant { //~ ERROR types=[[-];[];[]] + t: fn(A) +} + +#[rustc_variance] +enum Enum { //~ ERROR types=[[+, -, o];[];[]] + Foo(Covariant), + Bar(Contravariant), + Zed(Covariant,Contravariant) +} + +pub fn main() { } diff --git a/src/test/compile-fail/variance-unused-region-param.rs b/src/test/compile-fail/variance-unused-region-param.rs new file mode 100644 index 00000000000..5f504226370 --- /dev/null +++ b/src/test/compile-fail/variance-unused-region-param.rs @@ -0,0 +1,17 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we report an error for unused type parameters in types. + +struct SomeStruct<'a> { x: u32 } //~ ERROR parameter `'a` is never used +enum SomeEnum<'a> { Nothing } //~ ERROR parameter `'a` is never used +trait SomeTrait<'a> { fn foo(&self); } //~ ERROR parameter `'a` is never used + +fn main() {} diff --git a/src/test/compile-fail/variance-unused-type-param.rs b/src/test/compile-fail/variance-unused-type-param.rs new file mode 100644 index 00000000000..2e867ec3c93 --- /dev/null +++ b/src/test/compile-fail/variance-unused-type-param.rs @@ -0,0 +1,36 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +// Test that we report an error for unused type parameters in types and traits, +// and that we offer a helpful suggestion. + +struct SomeStruct { x: u32 } +//~^ ERROR parameter `A` is never used +//~| HELP PhantomData + +enum SomeEnum { Nothing } +//~^ ERROR parameter `A` is never used +//~| HELP PhantomData + +trait SomeTrait { fn foo(&self); } +//~^ ERROR parameter `A` is never used +//~| HELP PhantomFn + +// Here T might *appear* used, but in fact it isn't. +enum ListCell { +//~^ ERROR parameter `T` is never used +//~| HELP PhantomData + Cons(Box>), + Nil +} + +fn main() {} diff --git a/src/test/compile-fail/variance-use-contravariant-struct-1.rs b/src/test/compile-fail/variance-use-contravariant-struct-1.rs new file mode 100644 index 00000000000..d2fd2978750 --- /dev/null +++ b/src/test/compile-fail/variance-use-contravariant-struct-1.rs @@ -0,0 +1,26 @@ +// 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. + +// Test various uses of structs with distint variances to make sure +// they permit lifetimes to be approximated as expected. + +#![feature(rustc_attrs)] + +struct SomeStruct(fn(T)); + +fn foo<'min,'max>(v: SomeStruct<&'max ()>) + -> SomeStruct<&'min ()> + where 'max : 'min +{ + v //~ ERROR mismatched types +} + +#[rustc_error] +fn main() { } diff --git a/src/test/compile-fail/variance-use-contravariant-struct-2.rs b/src/test/compile-fail/variance-use-contravariant-struct-2.rs new file mode 100644 index 00000000000..b38fd0e9ffc --- /dev/null +++ b/src/test/compile-fail/variance-use-contravariant-struct-2.rs @@ -0,0 +1,27 @@ +// 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. + +// Test various uses of structs with distint variances to make sure +// they permit lifetimes to be approximated as expected. + +#![allow(dead_code)] +#![feature(rustc_attrs)] + +struct SomeStruct(fn(T)); + +fn bar<'min,'max>(v: SomeStruct<&'min ()>) + -> SomeStruct<&'max ()> + where 'max : 'min +{ + v +} + +#[rustc_error] +fn main() { } //~ ERROR compilation successful diff --git a/src/test/compile-fail/variance-use-covariant-struct-1.rs b/src/test/compile-fail/variance-use-covariant-struct-1.rs new file mode 100644 index 00000000000..2631cfc05e8 --- /dev/null +++ b/src/test/compile-fail/variance-use-covariant-struct-1.rs @@ -0,0 +1,23 @@ +// 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. + +// Test that a covariant struct does not permit the lifetime of a +// reference to be enlarged. + +struct SomeStruct(T); + +fn foo<'min,'max>(v: SomeStruct<&'min ()>) + -> SomeStruct<&'max ()> + where 'max : 'min +{ + v //~ ERROR mismatched types +} + +fn main() { } diff --git a/src/test/compile-fail/variance-use-covariant-struct-2.rs b/src/test/compile-fail/variance-use-covariant-struct-2.rs new file mode 100644 index 00000000000..d8e1a5f5f1c --- /dev/null +++ b/src/test/compile-fail/variance-use-covariant-struct-2.rs @@ -0,0 +1,26 @@ +// 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. + +// Test that a covariant struct permits the lifetime of a reference to +// be shortened. + +#![allow(dead_code)] +#![feature(rustc_attrs)] + +struct SomeStruct(T); + +fn foo<'min,'max>(v: SomeStruct<&'max ()>) + -> SomeStruct<&'min ()> + where 'max : 'min +{ + v +} + +#[rustc_error] fn main() { } //~ ERROR compilation successful diff --git a/src/test/compile-fail/variance-use-invariant-struct-1.rs b/src/test/compile-fail/variance-use-invariant-struct-1.rs new file mode 100644 index 00000000000..c89436b2094 --- /dev/null +++ b/src/test/compile-fail/variance-use-invariant-struct-1.rs @@ -0,0 +1,33 @@ +// 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. + +// Test various uses of structs with distint variances to make sure +// they permit lifetimes to be approximated as expected. + +#![feature(rustc_attrs)] + +struct SomeStruct(*mut T); + +fn foo<'min,'max>(v: SomeStruct<&'max ()>) + -> SomeStruct<&'min ()> + where 'max : 'min +{ + v //~ ERROR mismatched types +} + +fn bar<'min,'max>(v: SomeStruct<&'min ()>) + -> SomeStruct<&'max ()> + where 'max : 'min +{ + v //~ ERROR mismatched types +} + +#[rustc_error] +fn main() { } diff --git a/src/test/compile-fail/visible-private-types-generics.rs b/src/test/compile-fail/visible-private-types-generics.rs index 7ff18f8e088..1f2205b5c71 100644 --- a/src/test/compile-fail/visible-private-types-generics.rs +++ b/src/test/compile-fail/visible-private-types-generics.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo {} +trait Foo { + fn dummy(&self) { } +} pub fn f< T diff --git a/src/test/compile-fail/visible-private-types-supertrait.rs b/src/test/compile-fail/visible-private-types-supertrait.rs index dc6d446154a..9d9eae4a075 100644 --- a/src/test/compile-fail/visible-private-types-supertrait.rs +++ b/src/test/compile-fail/visible-private-types-supertrait.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo {} +trait Foo { + fn dummy(&self) { } +} pub trait Bar : Foo {} //~ ERROR private trait in exported type diff --git a/src/test/compile-fail/where-clause-method-substituion.rs b/src/test/compile-fail/where-clause-method-substituion.rs index a5108f005dc..bf614e6eb51 100644 --- a/src/test/compile-fail/where-clause-method-substituion.rs +++ b/src/test/compile-fail/where-clause-method-substituion.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo {} +trait Foo { + fn dummy(&self, t: T) { } +} trait Bar { fn method(&self) where A: Foo; diff --git a/src/test/compile-fail/where-clauses-not-parameter.rs b/src/test/compile-fail/where-clauses-not-parameter.rs index 313ae273c07..7968cc37090 100644 --- a/src/test/compile-fail/where-clauses-not-parameter.rs +++ b/src/test/compile-fail/where-clauses-not-parameter.rs @@ -21,7 +21,7 @@ fn test2() -> bool where Option : Eq {} #[derive(PartialEq)] //~^ ERROR cannot bound type `isize`, where clause bounds -enum Foo where isize : Eq { MkFoo } +enum Foo where isize : Eq { MkFoo(T) } //~^ ERROR cannot bound type `isize`, where clause bounds fn test3() -> bool where Option> : Eq {} @@ -31,7 +31,7 @@ fn test4() -> bool where Option> : Eq {} trait Baz where isize : Eq { //~^ ERROR cannot bound type `isize`, where clause bounds may only - fn baz() where String : Eq; //~ ERROR cannot bound type `collections::string::String` + fn baz(&self, t: T) where String : Eq; //~ ERROR cannot bound type `collections::string::String` //~^ ERROR cannot bound type `isize`, where clause } diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index a592484f1a4..bf26fc23d3c 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -177,10 +177,11 @@ #![omit_gdb_pretty_printer_section] use self::Enum1::{Variant1_1, Variant1_2}; +use std::marker::PhantomData; use std::ptr; struct Struct1; -struct GenericStruct; +struct GenericStruct(PhantomData<(T1,T2)>); enum Enum1 { Variant1_1, @@ -207,8 +208,8 @@ mod Mod1 { } } -trait Trait1 { } -trait Trait2 { } +trait Trait1 { fn dummy(&self) { } } +trait Trait2 { fn dummy(&self, _: T1, _:T2) { } } impl Trait1 for isize {} impl Trait2 for isize {} @@ -240,8 +241,10 @@ fn main() { // Structs let simple_struct = Struct1; - let generic_struct1: GenericStruct = GenericStruct; - let generic_struct2: GenericStruct usize> = GenericStruct; + let generic_struct1: GenericStruct = + GenericStruct(PhantomData); + let generic_struct2: GenericStruct usize> = + GenericStruct(PhantomData); let mod_struct = Mod1::Struct2; // Enums @@ -262,10 +265,10 @@ fn main() { // References let ref1 = (&Struct1, 0i32); - let ref2 = (&GenericStruct::, 0i32); + let ref2 = (&GenericStruct::(PhantomData), 0i32); let mut mut_struct1 = Struct1; - let mut mut_generic_struct = GenericStruct::; + let mut mut_generic_struct = GenericStruct::(PhantomData); let mut_ref1 = (&mut mut_struct1, 0i32); let mut_ref2 = (&mut mut_generic_struct, 0i32); diff --git a/src/test/pretty/empty-impl.rs b/src/test/pretty/empty-impl.rs index f22f1b40952..f5205de5c1f 100644 --- a/src/test/pretty/empty-impl.rs +++ b/src/test/pretty/empty-impl.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait X { } +trait X { fn dummy(&self) { } } impl X for uint { } -trait Y { } +trait Y { fn dummy(&self) { } } impl Y for uint { } diff --git a/src/test/pretty/path-type-bounds.rs b/src/test/pretty/path-type-bounds.rs index e27a3365a41..9e1f2aa8bfe 100644 --- a/src/test/pretty/path-type-bounds.rs +++ b/src/test/pretty/path-type-bounds.rs @@ -11,7 +11,9 @@ // pp-exact -trait Tr { } +trait Tr { + fn dummy(&self) { } +} impl Tr for int { } fn foo<'a>(x: Box) -> Box { x } diff --git a/src/test/run-fail/bug-811.rs b/src/test/run-fail/bug-811.rs index e46564f8076..4ad81197286 100644 --- a/src/test/run-fail/bug-811.rs +++ b/src/test/run-fail/bug-811.rs @@ -9,6 +9,9 @@ // except according to those terms. // error-pattern:quux + +use std::marker::PhantomData; + fn test00_start(ch: chan_t, message: int) { send(ch, message); } type task_id = int; @@ -17,6 +20,7 @@ type port_id = int; struct chan_t { task: task_id, port: port_id, + marker: PhantomData<*mut T>, } fn send(_ch: chan_t, _data: T) { panic!(); } diff --git a/src/test/run-make/rustdoc-json/foo.rs b/src/test/run-make/rustdoc-json/foo.rs index d57a7164cdb..3bd56c14193 100644 --- a/src/test/run-make/rustdoc-json/foo.rs +++ b/src/test/run-make/rustdoc-json/foo.rs @@ -21,5 +21,5 @@ pub mod bar { } /// *wow* - pub trait Doge { } + pub trait Doge { fn dummy(&self) { } } } diff --git a/src/test/run-make/rustdoc-negative-impl/foo.rs b/src/test/run-make/rustdoc-negative-impl/foo.rs index b5fcbf46c5c..6c56bcc9be6 100644 --- a/src/test/run-make/rustdoc-negative-impl/foo.rs +++ b/src/test/run-make/rustdoc-negative-impl/foo.rs @@ -13,7 +13,7 @@ // @matches foo/struct.Alpha.html '//pre' "pub struct Alpha" pub struct Alpha; // @matches foo/struct.Bravo.html '//pre' "pub struct Bravo" -pub struct Bravo; +pub struct Bravo(B); // @matches foo/struct.Alpha.html '//*[@class="impl"]//code' "impl !Send for Alpha" impl !Send for Alpha {} diff --git a/src/test/run-make/rustdoc-search-index/index.rs b/src/test/run-make/rustdoc-search-index/index.rs index dd68f2d6f1d..42469a21f22 100644 --- a/src/test/run-make/rustdoc-search-index/index.rs +++ b/src/test/run-make/rustdoc-search-index/index.rs @@ -21,6 +21,6 @@ mod private { } pub trait PrivateTrait { - fn trait_method() {} // @!has - priv_method + fn trait_method(&self) {} // @!has - priv_method } } diff --git a/src/test/run-make/rustdoc-smoke/foo.rs b/src/test/run-make/rustdoc-smoke/foo.rs index 0438c9aba35..f6b73021beb 100644 --- a/src/test/run-make/rustdoc-smoke/foo.rs +++ b/src/test/run-make/rustdoc-smoke/foo.rs @@ -26,7 +26,7 @@ pub mod bar { /// *wow* // @has foo/bar/trait.Doge.html - pub trait Doge { } + pub trait Doge { fn dummy(&self) { } } // @has foo/bar/struct.Foo.html pub struct Foo { x: int, y: uint } diff --git a/src/test/run-make/rustdoc-viewpath-self/foo.rs b/src/test/run-make/rustdoc-viewpath-self/foo.rs index da8f7393023..6fd47d84c30 100644 --- a/src/test/run-make/rustdoc-viewpath-self/foo.rs +++ b/src/test/run-make/rustdoc-viewpath-self/foo.rs @@ -9,7 +9,7 @@ // except according to those terms. pub mod io { - pub trait Reader { } + pub trait Reader { fn dummy(&self) { } } } pub enum Maybe { diff --git a/src/test/run-make/rustdoc-where/foo.rs b/src/test/run-make/rustdoc-where/foo.rs index 68fde60564e..91a7e1c9fd4 100644 --- a/src/test/run-make/rustdoc-where/foo.rs +++ b/src/test/run-make/rustdoc-where/foo.rs @@ -8,30 +8,33 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub trait MyTrait {} +pub trait MyTrait { fn dummy(&self) { } } // @has foo/struct.Alpha.html '//pre' "pub struct Alpha where A: MyTrait" -pub struct Alpha where A: MyTrait; +pub struct Alpha(A) where A: MyTrait; // @has foo/trait.Bravo.html '//pre' "pub trait Bravo where B: MyTrait" -pub trait Bravo where B: MyTrait {} +pub trait Bravo where B: MyTrait { fn get(&self, B: B); } // @has foo/fn.charlie.html '//pre' "pub fn charlie() where C: MyTrait" pub fn charlie() where C: MyTrait {} -pub struct Delta; +pub struct Delta(D); + // @has foo/struct.Delta.html '//*[@class="impl"]//code' \ // "impl Delta where D: MyTrait" impl Delta where D: MyTrait { pub fn delta() {} } -pub struct Echo; +pub struct Echo(E); + // @has foo/struct.Echo.html '//*[@class="impl"]//code' \ // "impl MyTrait for Echo where E: MyTrait" // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//code' \ // "impl MyTrait for Echo where E: MyTrait" impl MyTrait for Echo where E: MyTrait {} -pub enum Foxtrot {} +pub enum Foxtrot { Foxtrot1(F) } + // @has foo/enum.Foxtrot.html '//*[@class="impl"]//code' \ // "impl MyTrait for Foxtrot where F: MyTrait" // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//code' \ diff --git a/src/test/run-make/save-analysis/foo.rs b/src/test/run-make/save-analysis/foo.rs index fbbecfbf2a6..b6366ad6737 100644 --- a/src/test/run-make/save-analysis/foo.rs +++ b/src/test/run-make/save-analysis/foo.rs @@ -99,6 +99,7 @@ struct some_fields { type SF = some_fields; trait SuperTrait { + fn dummy(&self) { } } trait SomeTrait: SuperTrait { diff --git a/src/test/run-make/simd-ffi/simd.rs b/src/test/run-make/simd-ffi/simd.rs index 834a2adf01f..f418d5d1fb7 100755 --- a/src/test/run-make/simd-ffi/simd.rs +++ b/src/test/run-make/simd-ffi/simd.rs @@ -70,10 +70,14 @@ pub fn bar(a: i32x4, b: i32x4) -> i32x4 { } #[lang = "sized"] -trait Sized {} +pub trait Sized : PhantomFn {} #[lang = "copy"] -trait Copy {} +pub trait Copy : PhantomFn {} + +#[lang="phantom_fn"] +pub trait PhantomFn { } +impl PhantomFn for U { } mod core { pub mod marker { diff --git a/src/test/run-make/symbols-are-reasonable/lib.rs b/src/test/run-make/symbols-are-reasonable/lib.rs index 1e0570c95ac..e1f36ecda53 100644 --- a/src/test/run-make/symbols-are-reasonable/lib.rs +++ b/src/test/run-make/symbols-are-reasonable/lib.rs @@ -11,7 +11,7 @@ pub static X: &'static str = "foobarbaz"; pub static Y: &'static [u8] = include_bytes!("lib.rs"); -trait Foo {} +trait Foo { fn dummy(&self) { } } impl Foo for uint {} pub fn dummy() { diff --git a/src/test/run-make/target-specs/foo.rs b/src/test/run-make/target-specs/foo.rs index 365fc039a4e..acda8705b19 100644 --- a/src/test/run-make/target-specs/foo.rs +++ b/src/test/run-make/target-specs/foo.rs @@ -11,11 +11,15 @@ #![feature(lang_items, no_std)] #![no_std] +#[lang="phantom_fn"] +trait PhantomFn { } +impl PhantomFn for U { } + #[lang="copy"] -trait Copy { } +trait Copy : PhantomFn { } #[lang="sized"] -trait Sized { } +trait Sized : PhantomFn { } #[lang="start"] fn start(_main: *const u8, _argc: int, _argv: *const *const u8) -> int { 0 } diff --git a/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs b/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs index 195055f12d1..aecec44f6fd 100644 --- a/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs +++ b/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs @@ -25,7 +25,7 @@ impl Drop for Foo { } -trait Trait {} +trait Trait { fn dummy(&self) { } } impl Trait for Foo {} pub fn main() { diff --git a/src/test/run-pass-valgrind/dst-dtor-1.rs b/src/test/run-pass-valgrind/dst-dtor-1.rs index 47e2a18a999..c49a684de94 100644 --- a/src/test/run-pass-valgrind/dst-dtor-1.rs +++ b/src/test/run-pass-valgrind/dst-dtor-1.rs @@ -19,7 +19,7 @@ impl Drop for Foo { } } -trait Trait {} +trait Trait { fn dummy(&self) { } } impl Trait for Foo {} struct Fat { diff --git a/src/test/run-pass/associated-types-basic.rs b/src/test/run-pass/associated-types-basic.rs index 3314b613201..f5521f7da85 100644 --- a/src/test/run-pass/associated-types-basic.rs +++ b/src/test/run-pass/associated-types-basic.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo { +use std::marker::MarkerTrait; + +trait Foo : MarkerTrait { type T; } diff --git a/src/test/run-pass/associated-types-conditional-dispatch.rs b/src/test/run-pass/associated-types-conditional-dispatch.rs index f21b7183d70..aa65b0ed10b 100644 --- a/src/test/run-pass/associated-types-conditional-dispatch.rs +++ b/src/test/run-pass/associated-types-conditional-dispatch.rs @@ -14,6 +14,7 @@ // `Target=[A]`, then the impl marked with `(*)` is seen to conflict // with all the others. +use std::marker::PhantomData; use std::ops::Deref; pub trait MyEq { @@ -41,7 +42,8 @@ impl<'a, A, B, Lhs> MyEq<[B; 0]> for Lhs } struct DerefWithHelper { - pub helper: H + pub helper: H, + pub marker: PhantomData, } trait Helper { @@ -63,7 +65,8 @@ impl> Deref for DerefWithHelper { } pub fn check(x: T, y: T) -> bool { - let d: DerefWithHelper, T> = DerefWithHelper { helper: Some(x) }; + let d: DerefWithHelper, T> = DerefWithHelper { helper: Some(x), + marker: PhantomData }; d.eq(&y) } diff --git a/src/test/run-pass/associated-types-issue-20371.rs b/src/test/run-pass/associated-types-issue-20371.rs index d35b7331d4d..40ef7f3531c 100644 --- a/src/test/run-pass/associated-types-issue-20371.rs +++ b/src/test/run-pass/associated-types-issue-20371.rs @@ -11,6 +11,8 @@ // Test that we are able to have an impl that defines an associated type // before the actual trait. +use std::marker::MarkerTrait; + impl X for f64 { type Y = int; } -trait X {type Y; } +trait X : MarkerTrait { type Y; } fn main() {} diff --git a/src/test/run-pass/associated-types-issue-21212.rs b/src/test/run-pass/associated-types-issue-21212.rs index ced44250e4d..3c91577362a 100644 --- a/src/test/run-pass/associated-types-issue-21212.rs +++ b/src/test/run-pass/associated-types-issue-21212.rs @@ -20,7 +20,8 @@ pub trait Parser { panic!() } } -impl

Parser for P { + +impl

(&self, n: uint, pred: P) -> SplitsN> where P: FnMut(&T) -> bool { + fn splitn2

(&self, n: u32, pred: P) -> SplitsN> where P: FnMut(&T) -> bool { SliceExt2::split2(self, pred); loop {} } diff --git a/src/test/run-pass/associated-types-normalize-in-bounds.rs b/src/test/run-pass/associated-types-normalize-in-bounds.rs index 742bab0578e..94cfcb83653 100644 --- a/src/test/run-pass/associated-types-normalize-in-bounds.rs +++ b/src/test/run-pass/associated-types-normalize-in-bounds.rs @@ -11,15 +11,17 @@ // Test that we normalize associated types that appear in bounds; if // we didn't, the call to `self.split2()` fails to type check. -struct Splits<'a, T, P>; -struct SplitsN; +use std::marker::PhantomData; + +struct Splits<'a, T, P>(PhantomData<(&'a(),T,P)>); +struct SplitsN(PhantomData); trait SliceExt2 { type Item; fn split2<'a, P>(&'a self, pred: P) -> Splits<'a, Self::Item, P> where P: FnMut(&Self::Item) -> bool; - fn splitn2<'a, P>(&'a self, n: uint, pred: P) -> SplitsN> + fn splitn2<'a, P>(&'a self, n: usize, pred: P) -> SplitsN> where P: FnMut(&Self::Item) -> bool; } @@ -30,7 +32,7 @@ impl SliceExt2 for [T] { loop {} } - fn splitn2

(&self, n: uint, pred: P) -> SplitsN> where P: FnMut(&T) -> bool { + fn splitn2

(&self, n: usize, pred: P) -> SplitsN> where P: FnMut(&T) -> bool { self.split2(pred); loop {} } diff --git a/src/test/run-pass/associated-types-normalize-unifield-struct.rs b/src/test/run-pass/associated-types-normalize-unifield-struct.rs index 5aafe93067c..2288e19aae0 100644 --- a/src/test/run-pass/associated-types-normalize-unifield-struct.rs +++ b/src/test/run-pass/associated-types-normalize-unifield-struct.rs @@ -13,7 +13,10 @@ pub trait OffsetState: Sized {} -pub trait Offset { type State: OffsetState; } +pub trait Offset { + type State: OffsetState; + fn dummy(&self) { } +} #[derive(Copy)] pub struct X; impl Offset for X { type State = Y; } diff --git a/src/test/run-pass/associated-types-projection-from-known-type-in-impl.rs b/src/test/run-pass/associated-types-projection-from-known-type-in-impl.rs index 0a1a8589dec..c65d2db9b0c 100644 --- a/src/test/run-pass/associated-types-projection-from-known-type-in-impl.rs +++ b/src/test/run-pass/associated-types-projection-from-known-type-in-impl.rs @@ -13,6 +13,8 @@ trait Int { type T; + + fn dummy(&self) { } } trait NonZero diff --git a/src/test/run-pass/associated-types-projection-in-object-type.rs b/src/test/run-pass/associated-types-projection-in-object-type.rs index 44dd49b7297..a9c34a605ce 100644 --- a/src/test/run-pass/associated-types-projection-in-object-type.rs +++ b/src/test/run-pass/associated-types-projection-in-object-type.rs @@ -18,6 +18,8 @@ use std::cell::RefCell; pub trait Subscriber { type Input; + + fn dummy(&self) { } } pub trait Publisher<'a> { diff --git a/src/test/run-pass/associated-types-projection-in-supertrait.rs b/src/test/run-pass/associated-types-projection-in-supertrait.rs index e6fec675b03..4d2358fae27 100644 --- a/src/test/run-pass/associated-types-projection-in-supertrait.rs +++ b/src/test/run-pass/associated-types-projection-in-supertrait.rs @@ -14,6 +14,8 @@ trait A { type TA; + + fn dummy(&self) { } } trait B diff --git a/src/test/run-pass/associated-types-projection-in-where-clause.rs b/src/test/run-pass/associated-types-projection-in-where-clause.rs index 10a459f3c36..3f3f4fbd1d6 100644 --- a/src/test/run-pass/associated-types-projection-in-where-clause.rs +++ b/src/test/run-pass/associated-types-projection-in-where-clause.rs @@ -13,6 +13,8 @@ trait Int { type T; + + fn dummy(&self) { } } trait NonZero diff --git a/src/test/run-pass/associated-types-ref-in-struct-literal.rs b/src/test/run-pass/associated-types-ref-in-struct-literal.rs index 022c8f4cd01..67fe11d8fed 100644 --- a/src/test/run-pass/associated-types-ref-in-struct-literal.rs +++ b/src/test/run-pass/associated-types-ref-in-struct-literal.rs @@ -12,6 +12,8 @@ pub trait Foo { type Bar; + + fn dummy(&self) { } } impl Foo for int { diff --git a/src/test/run-pass/associated-types-resolve-lifetime.rs b/src/test/run-pass/associated-types-resolve-lifetime.rs index e7a8061a346..a4b0b1a6e03 100644 --- a/src/test/run-pass/associated-types-resolve-lifetime.rs +++ b/src/test/run-pass/associated-types-resolve-lifetime.rs @@ -15,6 +15,8 @@ trait Get { trait Trait<'a> { type T: 'static; type U: Get<&'a int>; + + fn dummy(&'a self) { } } fn main() {} diff --git a/src/test/run-pass/associated-types-struct-field-named.rs b/src/test/run-pass/associated-types-struct-field-named.rs index 1ded34ff3ff..8667f6c8430 100644 --- a/src/test/run-pass/associated-types-struct-field-named.rs +++ b/src/test/run-pass/associated-types-struct-field-named.rs @@ -13,6 +13,8 @@ pub trait UnifyKey { type Value; + + fn dummy(&self) { } } pub struct Node { diff --git a/src/test/run-pass/associated-types-struct-field-numbered.rs b/src/test/run-pass/associated-types-struct-field-numbered.rs index 3669dec4fbd..9503f78a71b 100644 --- a/src/test/run-pass/associated-types-struct-field-numbered.rs +++ b/src/test/run-pass/associated-types-struct-field-numbered.rs @@ -13,6 +13,8 @@ pub trait UnifyKey { type Value; + + fn dummy(&self) { } } pub struct Node(K, K::Value); diff --git a/src/test/run-pass/associated-types-sugar-path.rs b/src/test/run-pass/associated-types-sugar-path.rs index 3b70e941ac5..c068065ac6a 100644 --- a/src/test/run-pass/associated-types-sugar-path.rs +++ b/src/test/run-pass/associated-types-sugar-path.rs @@ -31,8 +31,9 @@ pub fn bar(a: T, x: T::A) -> T::A { // Using a type via an impl. trait C { fn f(); + fn g(&self) { } } -struct B; +struct B(X); impl C for B { fn f() { let x: T::A = panic!(); diff --git a/src/test/run-pass/borrowck-trait-lifetime.rs b/src/test/run-pass/borrowck-trait-lifetime.rs index b39f03a93c9..be0c88f557c 100644 --- a/src/test/run-pass/borrowck-trait-lifetime.rs +++ b/src/test/run-pass/borrowck-trait-lifetime.rs @@ -12,8 +12,11 @@ // to the same lifetime on a trait succeeds. See issue #10766. #![allow(dead_code)] + +use std::marker; + fn main() { - trait T {} + trait T : marker::MarkerTrait {} fn f<'a, V: T>(v: &'a V) -> &'a T { v as &'a T diff --git a/src/test/run-pass/bug-7295.rs b/src/test/run-pass/bug-7295.rs index ea711d78dd2..143ebfdabfa 100644 --- a/src/test/run-pass/bug-7295.rs +++ b/src/test/run-pass/bug-7295.rs @@ -9,10 +9,10 @@ // except according to those terms. pub trait Foo { - fn func1(&self, t: U); + fn func1(&self, t: U, w: T); - fn func2(&self, t: U) { - self.func1(t); + fn func2(&self, t: U, w: T) { + self.func1(t, w); } } diff --git a/src/test/run-pass/builtin-superkinds-in-metadata.rs b/src/test/run-pass/builtin-superkinds-in-metadata.rs index c115415bb9b..7eaed910124 100644 --- a/src/test/run-pass/builtin-superkinds-in-metadata.rs +++ b/src/test/run-pass/builtin-superkinds-in-metadata.rs @@ -16,6 +16,7 @@ extern crate trait_superkinds_in_metadata; use trait_superkinds_in_metadata::{RequiresRequiresShareAndSend, RequiresShare}; use trait_superkinds_in_metadata::{RequiresCopy}; +use std::marker; #[derive(Copy)] struct X(T); diff --git a/src/test/run-pass/builtin-superkinds-phantom-typaram.rs b/src/test/run-pass/builtin-superkinds-phantom-typaram.rs index 7e1b2821937..964c28dc945 100644 --- a/src/test/run-pass/builtin-superkinds-phantom-typaram.rs +++ b/src/test/run-pass/builtin-superkinds-phantom-typaram.rs @@ -12,10 +12,12 @@ // super-builtin-kind of a trait, if the type parameter is never used, // the type can implement the trait anyway. +use std::marker; + trait Foo : Send { } -struct X(()); +struct X { marker: marker::PhantomData } -impl Foo for X { } +impl Foo for X { } pub fn main() { } diff --git a/src/test/run-pass/class-typarams.rs b/src/test/run-pass/class-typarams.rs index 68457095944..b56a749d33b 100644 --- a/src/test/run-pass/class-typarams.rs +++ b/src/test/run-pass/class-typarams.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker::PhantomData; + struct cat { meows : uint, - how_hungry : int, + m: PhantomData } impl cat { @@ -22,7 +24,8 @@ impl cat { fn cat(in_x : uint, in_y : int) -> cat { cat { meows: in_x, - how_hungry: in_y + how_hungry: in_y, + m: PhantomData } } diff --git a/src/test/run-pass/dst-coercions.rs b/src/test/run-pass/dst-coercions.rs index dbad546ce1a..30ed0b8e402 100644 --- a/src/test/run-pass/dst-coercions.rs +++ b/src/test/run-pass/dst-coercions.rs @@ -11,7 +11,7 @@ // Test coercions involving DST and/or raw pointers struct S; -trait T {} +trait T { fn dummy(&self) { } } impl T for S {} pub fn main() { diff --git a/src/test/run-pass/enum-null-pointer-opt.rs b/src/test/run-pass/enum-null-pointer-opt.rs index 797c26556aa..023376ce473 100644 --- a/src/test/run-pass/enum-null-pointer-opt.rs +++ b/src/test/run-pass/enum-null-pointer-opt.rs @@ -16,7 +16,7 @@ use std::mem::size_of; use std::rc::Rc; use std::sync::Arc; -trait Trait {} +trait Trait { fn dummy(&self) { } } fn main() { // Functions diff --git a/src/test/run-pass/explicit-self-generic.rs b/src/test/run-pass/explicit-self-generic.rs index 066a5f9580a..382c5c58e92 100644 --- a/src/test/run-pass/explicit-self-generic.rs +++ b/src/test/run-pass/explicit-self-generic.rs @@ -15,21 +15,19 @@ struct LM { resize_at: uint, size: uint } enum HashMap { - HashMap_(LM) + HashMap_(LM, Vec<(K,V)>) } -impl Copy for HashMap {} - fn linear_map() -> HashMap { HashMap::HashMap_(LM{ resize_at: 32, - size: 0}) + size: 0}, Vec::new()) } impl HashMap { pub fn len(&mut self) -> uint { match *self { - HashMap::HashMap_(l) => l.size + HashMap::HashMap_(ref l, _) => l.size } } } diff --git a/src/test/run-pass/generic-default-type-params-cross-crate.rs b/src/test/run-pass/generic-default-type-params-cross-crate.rs index ed8c6e73255..bf02b82d1a0 100644 --- a/src/test/run-pass/generic-default-type-params-cross-crate.rs +++ b/src/test/run-pass/generic-default-type-params-cross-crate.rs @@ -12,13 +12,13 @@ extern crate default_type_params_xc; -struct Vec; +struct Vec(Option<(T,A)>); struct Foo; fn main() { - let _a = Vec::; - let _b = Vec::; - let _c = default_type_params_xc::FakeVec::; - let _d = default_type_params_xc::FakeVec::; + let _a = Vec::(None); + let _b = Vec::(None); + let _c = default_type_params_xc::FakeVec:: { f: None }; + let _d = default_type_params_xc::FakeVec:: { f: None }; } diff --git a/src/test/run-pass/hrtb-opt-in-copy.rs b/src/test/run-pass/hrtb-opt-in-copy.rs index 9c9f95f61e9..7b16bb867e7 100644 --- a/src/test/run-pass/hrtb-opt-in-copy.rs +++ b/src/test/run-pass/hrtb-opt-in-copy.rs @@ -18,7 +18,7 @@ #![allow(dead_code)] -use std::marker; +use std::marker::PhantomData; #[derive(Copy)] struct Foo { x: T } @@ -26,7 +26,7 @@ struct Foo { x: T } type Ty<'tcx> = &'tcx TyS<'tcx>; enum TyS<'tcx> { - Boop(marker::InvariantLifetime<'tcx>) + Boop(PhantomData<*mut &'tcx ()>) } #[derive(Copy)] diff --git a/src/test/run-pass/inner-static.rs b/src/test/run-pass/inner-static.rs index f9b430c1553..e4026a8fd01 100644 --- a/src/test/run-pass/inner-static.rs +++ b/src/test/run-pass/inner-static.rs @@ -13,9 +13,9 @@ extern crate inner_static; pub fn main() { - let a = inner_static::A::<()>; - let b = inner_static::B::<()>; - let c = inner_static::test::A::<()>; + let a = inner_static::A::<()> { v: () }; + let b = inner_static::B::<()> { v: () }; + let c = inner_static::test::A::<()> { v: () }; assert_eq!(a.bar(), 2); assert_eq!(b.bar(), 4); assert_eq!(c.bar(), 6); diff --git a/src/test/run-pass/issue-10456.rs b/src/test/run-pass/issue-10456.rs index b714d87f4ef..da73c4b27ac 100644 --- a/src/test/run-pass/issue-10456.rs +++ b/src/test/run-pass/issue-10456.rs @@ -14,7 +14,9 @@ pub trait Bar { fn bar(&self); } -pub trait Baz {} +pub trait Baz { + fn baz(&self) { } +} impl Bar for T { fn bar(&self) {} diff --git a/src/test/run-pass/issue-10802.rs b/src/test/run-pass/issue-10802.rs index de2b4c51e52..174a69e1135 100644 --- a/src/test/run-pass/issue-10802.rs +++ b/src/test/run-pass/issue-10802.rs @@ -29,7 +29,7 @@ impl Drop for DroppableEnum { } } -trait MyTrait { } +trait MyTrait { fn dummy(&self) { } } impl MyTrait for Box {} impl MyTrait for Box {} diff --git a/src/test/run-pass/issue-10902.rs b/src/test/run-pass/issue-10902.rs index 324a1701b2f..7fab6662ee0 100644 --- a/src/test/run-pass/issue-10902.rs +++ b/src/test/run-pass/issue-10902.rs @@ -9,7 +9,7 @@ // except according to those terms. pub mod two_tuple { - pub trait T {} + pub trait T { fn dummy(&self) { } } pub struct P<'a>(&'a (T + 'a), &'a (T + 'a)); pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> { P(car, cdr) @@ -17,7 +17,7 @@ pub mod two_tuple { } pub mod two_fields { - pub trait T {} + pub trait T { fn dummy(&self) { } } pub struct P<'a> { car: &'a (T + 'a), cdr: &'a (T + 'a) } pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> { P{ car: car, cdr: cdr } diff --git a/src/test/run-pass/issue-11205.rs b/src/test/run-pass/issue-11205.rs index d7c6c1b1bb2..1325b51a54f 100644 --- a/src/test/run-pass/issue-11205.rs +++ b/src/test/run-pass/issue-11205.rs @@ -12,7 +12,7 @@ #![allow(unknown_features)] #![feature(box_syntax)] -trait Foo {} +trait Foo { fn dummy(&self) { } } impl Foo for int {} fn foo(_: [&Foo; 2]) {} fn foos(_: &[&Foo]) {} diff --git a/src/test/run-pass/issue-11384.rs b/src/test/run-pass/issue-11384.rs index a511149b05e..26634fabf5a 100644 --- a/src/test/run-pass/issue-11384.rs +++ b/src/test/run-pass/issue-11384.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Common {} +trait Common { fn dummy(&self) { } } impl<'t, T> Common for (T, &'t T) {} diff --git a/src/test/run-pass/issue-11612.rs b/src/test/run-pass/issue-11612.rs index fa25d25df05..3c69377b375 100644 --- a/src/test/run-pass/issue-11612.rs +++ b/src/test/run-pass/issue-11612.rs @@ -12,7 +12,7 @@ // We weren't updating the auto adjustments with all the resolved // type information after type check. -trait A {} +trait A { fn dummy(&self) { } } struct B<'a, T:'a> { f: &'a T diff --git a/src/test/run-pass/issue-11677.rs b/src/test/run-pass/issue-11677.rs index 6fa45058694..7cccac4483d 100644 --- a/src/test/run-pass/issue-11677.rs +++ b/src/test/run-pass/issue-11677.rs @@ -14,13 +14,18 @@ // this code used to cause an ICE -trait X {} +use std::marker; + +trait X { + fn dummy(&self) -> T { panic!() } +} struct S {f: Box+'static>, g: Box+'static>} struct F; -impl X for F {} +impl X for F { +} fn main() { S {f: box F, g: box F}; diff --git a/src/test/run-pass/issue-13105.rs b/src/test/run-pass/issue-13105.rs index 7fab36bd64e..64807dc44e0 100644 --- a/src/test/run-pass/issue-13105.rs +++ b/src/test/run-pass/issue-13105.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo { +use std::marker::MarkerTrait; + +trait Foo : MarkerTrait { fn quux(u8) {} } diff --git a/src/test/run-pass/issue-14399.rs b/src/test/run-pass/issue-14399.rs index 7e533c2cf86..4f3db1352bb 100644 --- a/src/test/run-pass/issue-14399.rs +++ b/src/test/run-pass/issue-14399.rs @@ -19,7 +19,7 @@ #[derive(Clone)] struct B1; -trait A {} +trait A : std::marker::MarkerTrait {} impl A for B1 {} fn main() { diff --git a/src/test/run-pass/issue-14589.rs b/src/test/run-pass/issue-14589.rs index d9763baa826..71d88ee6215 100644 --- a/src/test/run-pass/issue-14589.rs +++ b/src/test/run-pass/issue-14589.rs @@ -17,17 +17,18 @@ fn main() { send::>(box Output(0)); Test::>::foo(box Output(0)); - Test::>.send(box Output(0)); + Test::>::new().send(box Output(0)); } fn send(_: T) {} -struct Test; +struct Test { marker: std::marker::PhantomData } impl Test { + fn new() -> Test { Test { marker: ::std::marker::PhantomData } } fn foo(_: T) {} fn send(&self, _: T) {} } -trait Foo {} +trait Foo { fn dummy(&self) { }} struct Output(int); impl Foo for Output {} diff --git a/src/test/run-pass/issue-14958.rs b/src/test/run-pass/issue-14958.rs index 814a743648d..6335f79be6c 100644 --- a/src/test/run-pass/issue-14958.rs +++ b/src/test/run-pass/issue-14958.rs @@ -10,7 +10,7 @@ #![feature(unboxed_closures)] -trait Foo {} +trait Foo { fn dummy(&self) { }} struct Bar; diff --git a/src/test/run-pass/issue-14959.rs b/src/test/run-pass/issue-14959.rs index 33281d7d78f..53d0f7dae05 100644 --- a/src/test/run-pass/issue-14959.rs +++ b/src/test/run-pass/issue-14959.rs @@ -12,8 +12,8 @@ use std::ops::Fn; -trait Response {} -trait Request {} +trait Response { fn dummy(&self) { } } +trait Request { fn dummy(&self) { } } trait Ingot { fn enter(&mut self, _: &mut R, _: &mut S, a: &mut Alloy) -> Status; } @@ -21,7 +21,7 @@ trait Ingot { #[allow(dead_code)] struct HelloWorld; -struct SendFile<'a>; +struct SendFile; struct Alloy; enum Status { Continue @@ -33,7 +33,7 @@ impl Alloy { } } -impl<'a, 'b> Fn<(&'b mut (Response+'b),)> for SendFile<'a> { +impl<'b> Fn<(&'b mut (Response+'b),)> for SendFile { type Output = (); extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {} diff --git a/src/test/run-pass/issue-15858.rs b/src/test/run-pass/issue-15858.rs index c75c6725461..6a4f78442d1 100644 --- a/src/test/run-pass/issue-15858.rs +++ b/src/test/run-pass/issue-15858.rs @@ -12,21 +12,21 @@ static mut DROP_RAN: bool = false; -trait Bar<'b> { +trait Bar { fn do_something(&mut self); } -struct BarImpl<'b>; +struct BarImpl; -impl<'b> Bar<'b> for BarImpl<'b> { +impl Bar for BarImpl { fn do_something(&mut self) {} } -struct Foo; +struct Foo(B); #[unsafe_destructor] -impl<'b, B: Bar<'b>> Drop for Foo { +impl Drop for Foo { fn drop(&mut self) { unsafe { DROP_RAN = true; @@ -37,7 +37,7 @@ impl<'b, B: Bar<'b>> Drop for Foo { fn main() { { - let _x: Foo = Foo; + let _x: Foo = Foo(BarImpl); } unsafe { assert_eq!(DROP_RAN, true); diff --git a/src/test/run-pass/issue-16596.rs b/src/test/run-pass/issue-16596.rs index e01de3a3262..1ba7b142e5e 100644 --- a/src/test/run-pass/issue-16596.rs +++ b/src/test/run-pass/issue-16596.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait MatrixRow {} +trait MatrixRow { fn dummy(&self) { }} struct Mat; diff --git a/src/test/run-pass/issue-16643.rs b/src/test/run-pass/issue-16643.rs index b118c9573cd..4e57c55c5f7 100644 --- a/src/test/run-pass/issue-16643.rs +++ b/src/test/run-pass/issue-16643.rs @@ -13,5 +13,5 @@ extern crate "issue-16643" as i; pub fn main() { - i::TreeBuilder::.process_token(); + i::TreeBuilder { h: 3u }.process_token(); } diff --git a/src/test/run-pass/issue-17662.rs b/src/test/run-pass/issue-17662.rs index 45e70f59f33..7bd41cc5b52 100644 --- a/src/test/run-pass/issue-17662.rs +++ b/src/test/run-pass/issue-17662.rs @@ -12,12 +12,14 @@ extern crate "issue-17662" as i; -struct Bar<'a>; +use std::marker; + +struct Bar<'a> { m: marker::PhantomData<&'a ()> } impl<'a> i::Foo<'a, uint> for Bar<'a> { fn foo(&self) -> uint { 5_usize } } pub fn main() { - assert_eq!(i::foo(&Bar), 5); + assert_eq!(i::foo(&Bar { m: marker::PhantomData }), 5); } diff --git a/src/test/run-pass/issue-17732.rs b/src/test/run-pass/issue-17732.rs index b4bd55da597..de9611f2592 100644 --- a/src/test/run-pass/issue-17732.rs +++ b/src/test/run-pass/issue-17732.rs @@ -10,8 +10,9 @@ trait Person { type string; + fn dummy(&self) { } } -struct Someone; +struct Someone(std::marker::PhantomData

); fn main() {} diff --git a/src/test/run-pass/issue-17771.rs b/src/test/run-pass/issue-17771.rs index 1e9550acef4..2f1b0342b8e 100644 --- a/src/test/run-pass/issue-17771.rs +++ b/src/test/run-pass/issue-17771.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Aaa {} +trait Aaa { fn dummy(&self) { } } impl<'a> Aaa for &'a mut (Aaa + 'a) {} diff --git a/src/test/run-pass/issue-17816.rs b/src/test/run-pass/issue-17816.rs index f8fbd680dcb..a976eccf89e 100644 --- a/src/test/run-pass/issue-17816.rs +++ b/src/test/run-pass/issue-17816.rs @@ -10,9 +10,11 @@ #![feature(unboxed_closures)] +use std::marker::PhantomData; + fn main() { - struct Symbol<'a, F: Fn(Vec<&'a str>) -> &'a str> { function: F } + struct Symbol<'a, F: Fn(Vec<&'a str>) -> &'a str> { function: F, marker: PhantomData<&'a ()> } let f = |x: Vec<&str>| -> &str "foobar"; - let sym = Symbol { function: f }; + let sym = Symbol { function: f, marker: PhantomData }; (sym.function)(vec![]); } diff --git a/src/test/run-pass/issue-17904.rs b/src/test/run-pass/issue-17904.rs index 3ce347d67e3..58a0872a571 100644 --- a/src/test/run-pass/issue-17904.rs +++ b/src/test/run-pass/issue-17904.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Foo where T: Copy; +// Test that we can parse where clauses on various forms of tuple +// structs. + struct Bar(T) where T: Copy; struct Bleh(T, U) where T: Copy, U: Sized; struct Baz where T: Copy { diff --git a/src/test/run-pass/issue-18232.rs b/src/test/run-pass/issue-18232.rs index 15cf5870d40..67b3239d351 100644 --- a/src/test/run-pass/issue-18232.rs +++ b/src/test/run-pass/issue-18232.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Cursor<'a>; +struct Cursor<'a>(::std::marker::PhantomData<&'a ()>); trait CursorNavigator { fn init_cursor<'a, 'b:'a>(&'a self, cursor: &mut Cursor<'b>) -> bool; @@ -23,7 +23,7 @@ impl CursorNavigator for SimpleNavigator { } fn main() { - let mut c = Cursor; + let mut c = Cursor(::std::marker::PhantomData); let n = SimpleNavigator; n.init_cursor(&mut c); } diff --git a/src/test/run-pass/issue-18906.rs b/src/test/run-pass/issue-18906.rs index 11ffb4198da..16dd84315ed 100644 --- a/src/test/run-pass/issue-18906.rs +++ b/src/test/run-pass/issue-18906.rs @@ -24,7 +24,7 @@ fn bar(k: &K, q: &Q) where K: Borrow, Q: Foo { q.foo(k.borrow()) } -struct MyTree; +struct MyTree(K); impl MyTree { // This caused a failure in #18906 diff --git a/src/test/run-pass/issue-19121.rs b/src/test/run-pass/issue-19121.rs index d95f74ef2a2..222f67af437 100644 --- a/src/test/run-pass/issue-19121.rs +++ b/src/test/run-pass/issue-19121.rs @@ -13,6 +13,8 @@ trait Foo { type A; + + fn dummy(&self) { } } fn bar(x: &Foo) {} diff --git a/src/test/run-pass/issue-19129-2.rs b/src/test/run-pass/issue-19129-2.rs index d6b3a1908b8..cf0f48e025a 100644 --- a/src/test/run-pass/issue-19129-2.rs +++ b/src/test/run-pass/issue-19129-2.rs @@ -11,7 +11,7 @@ trait Trait { type Output; - fn method() -> bool { false } + fn method(&self, i: Input) -> bool { false } } fn main() {} diff --git a/src/test/run-pass/issue-19135.rs b/src/test/run-pass/issue-19135.rs index 031a63ba474..5e6dd567d63 100644 --- a/src/test/run-pass/issue-19135.rs +++ b/src/test/run-pass/issue-19135.rs @@ -10,13 +10,15 @@ #![feature(unboxed_closures)] +use std::marker::PhantomData; + #[derive(Debug)] -struct LifetimeStruct<'a>; +struct LifetimeStruct<'a>(PhantomData<&'a ()>); fn main() { takes_hrtb_closure(|lts| println!("{:?}", lts)); } fn takes_hrtb_closureFnMut(LifetimeStruct<'a>)>(mut f: F) { - f(LifetimeStruct); + f(LifetimeStruct(PhantomData)); } diff --git a/src/test/run-pass/issue-19358.rs b/src/test/run-pass/issue-19358.rs index ff657376ecc..8b5269ab92f 100644 --- a/src/test/run-pass/issue-19358.rs +++ b/src/test/run-pass/issue-19358.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Trait {} +trait Trait { fn dummy(&self) { } } #[derive(Debug)] struct Foo { diff --git a/src/test/run-pass/issue-19398.rs b/src/test/run-pass/issue-19398.rs index 1196162568a..e603167b26b 100644 --- a/src/test/run-pass/issue-19398.rs +++ b/src/test/run-pass/issue-19398.rs @@ -9,11 +9,11 @@ // except according to those terms. trait T { - unsafe extern "Rust" fn foo(); + unsafe extern "Rust" fn foo(&self); } impl T for () { - unsafe extern "Rust" fn foo() {} + unsafe extern "Rust" fn foo(&self) {} } fn main() {} diff --git a/src/test/run-pass/issue-19479.rs b/src/test/run-pass/issue-19479.rs index 91bc645b2d4..38a7af3a695 100644 --- a/src/test/run-pass/issue-19479.rs +++ b/src/test/run-pass/issue-19479.rs @@ -8,12 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Base {} +trait Base { + fn dummy(&self) { } +} trait AssocA { type X: Base; + fn dummy(&self) { } } trait AssocB { type Y: Base; + fn dummy(&self) { } } impl AssocB for T { type Y = ::X; diff --git a/src/test/run-pass/issue-19631.rs b/src/test/run-pass/issue-19631.rs index 43116f63641..7bb0d055b84 100644 --- a/src/test/run-pass/issue-19631.rs +++ b/src/test/run-pass/issue-19631.rs @@ -10,6 +10,7 @@ trait PoolManager { type C; + fn dummy(&self) { } } struct InnerPool { diff --git a/src/test/run-pass/issue-19632.rs b/src/test/run-pass/issue-19632.rs index 01a073a6889..4339339d74c 100644 --- a/src/test/run-pass/issue-19632.rs +++ b/src/test/run-pass/issue-19632.rs @@ -10,6 +10,7 @@ trait PoolManager { type C; + fn dummy(&self) { } } struct InnerPool { diff --git a/src/test/run-pass/issue-20055-box-trait.rs b/src/test/run-pass/issue-20055-box-trait.rs index 836e78b5b51..572a0d82528 100644 --- a/src/test/run-pass/issue-20055-box-trait.rs +++ b/src/test/run-pass/issue-20055-box-trait.rs @@ -16,7 +16,9 @@ // whichever arm is run, and subsequently dropped at the end of the // statement surrounding the `match`. -trait Boo { } +trait Boo { + fn dummy(&self) { } +} impl Boo for [i8; 1] { } impl Boo for [i8; 2] { } diff --git a/src/test/run-pass/issue-20343.rs b/src/test/run-pass/issue-20343.rs index 79034a4a4a6..2f9e8feed24 100644 --- a/src/test/run-pass/issue-20343.rs +++ b/src/test/run-pass/issue-20343.rs @@ -16,7 +16,7 @@ struct B { b: u32 } struct C; struct D; -trait T {} +trait T { fn dummy(&self, a: A) { } } impl T for () {} impl B { diff --git a/src/test/run-pass/issue-20763-1.rs b/src/test/run-pass/issue-20763-1.rs index 911ee715da2..97c06ac9826 100644 --- a/src/test/run-pass/issue-20763-1.rs +++ b/src/test/run-pass/issue-20763-1.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait T0 { type O; } +trait T0 { + type O; + fn dummy(&self) { } +} struct S(A); impl T0 for S { type O = A; } diff --git a/src/test/run-pass/issue-20763-2.rs b/src/test/run-pass/issue-20763-2.rs index a17c7b6ade4..d9701763571 100644 --- a/src/test/run-pass/issue-20763-2.rs +++ b/src/test/run-pass/issue-20763-2.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait T0 { type O; } +trait T0 { + type O; + fn dummy(&self) { } +} struct S(A); impl T0 for S { type O = A; } diff --git a/src/test/run-pass/issue-21363.rs b/src/test/run-pass/issue-21363.rs index 2fc1d9fd643..71bb3d39fe1 100644 --- a/src/test/run-pass/issue-21363.rs +++ b/src/test/run-pass/issue-21363.rs @@ -12,6 +12,7 @@ trait Iterator { type Item; + fn dummy(&self) { } } impl<'a, T> Iterator for &'a mut (Iterator + 'a) { diff --git a/src/test/run-pass/issue-21909.rs b/src/test/run-pass/issue-21909.rs index 5bbc90b2606..55b61dd1945 100644 --- a/src/test/run-pass/issue-21909.rs +++ b/src/test/run-pass/issue-21909.rs @@ -8,11 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait A {} +trait A { + fn dummy(&self, arg: X); +} trait B { type X; type Y: A; + + fn dummy(&self); } fn main () { } diff --git a/src/test/run-pass/issue-2311-2.rs b/src/test/run-pass/issue-2311-2.rs index e0b98ab1965..5529d51b408 100644 --- a/src/test/run-pass/issue-2311-2.rs +++ b/src/test/run-pass/issue-2311-2.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait clam { } +trait clam { + fn get(self) -> A; +} + struct foo { x: A, } diff --git a/src/test/run-pass/issue-2311.rs b/src/test/run-pass/issue-2311.rs index dc873ed08d7..b6b3114e2a4 100644 --- a/src/test/run-pass/issue-2311.rs +++ b/src/test/run-pass/issue-2311.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait clam { } +trait clam { fn get(self) -> A; } trait foo { fn bar>(&self, c: C) -> B; } diff --git a/src/test/run-pass/issue-2312.rs b/src/test/run-pass/issue-2312.rs index 8c597552d75..3f273b56efd 100644 --- a/src/test/run-pass/issue-2312.rs +++ b/src/test/run-pass/issue-2312.rs @@ -10,7 +10,7 @@ // Testing that the B's are resolved -trait clam { } +trait clam { fn get(self) -> A; } struct foo(int); diff --git a/src/test/run-pass/issue-2611-3.rs b/src/test/run-pass/issue-2611-3.rs index 2608c89d155..c005699ce30 100644 --- a/src/test/run-pass/issue-2611-3.rs +++ b/src/test/run-pass/issue-2611-3.rs @@ -12,7 +12,7 @@ // than the traits require. trait A { - fn b(x: C) -> C; + fn b(&self, x: C) -> C; } struct E { @@ -20,7 +20,7 @@ struct E { } impl A for E { - fn b(_x: F) -> F { panic!() } + fn b(&self, _x: F) -> F { panic!() } //~^ ERROR in method `b`, type parameter 0 has 1 bound, but } diff --git a/src/test/run-pass/issue-2734.rs b/src/test/run-pass/issue-2734.rs index 7ca439a1a19..a7b53db6b05 100644 --- a/src/test/run-pass/issue-2734.rs +++ b/src/test/run-pass/issue-2734.rs @@ -11,7 +11,9 @@ #![allow(unknown_features)] #![feature(box_syntax)] -trait hax { } +trait hax { + fn dummy(&self) { } +} impl hax for A { } fn perform_hax(x: Box) -> Box { diff --git a/src/test/run-pass/issue-2735.rs b/src/test/run-pass/issue-2735.rs index 962359537bf..1594b94879c 100644 --- a/src/test/run-pass/issue-2735.rs +++ b/src/test/run-pass/issue-2735.rs @@ -11,7 +11,9 @@ #![allow(unknown_features)] #![feature(box_syntax)] -trait hax { } +trait hax { + fn dummy(&self) { } +} impl hax for A { } fn perform_hax(x: Box) -> Box { diff --git a/src/test/run-pass/issue-4107.rs b/src/test/run-pass/issue-4107.rs index 2ed662e9f2d..d660f300ada 100644 --- a/src/test/run-pass/issue-4107.rs +++ b/src/test/run-pass/issue-4107.rs @@ -9,14 +9,14 @@ // except according to those terms. pub fn main() { - let _id: &Mat2 = &Matrix::identity(); + let _id: &Mat2 = &Matrix::identity(1.0); } -pub trait Index { } +pub trait Index { fn get(&self, Index) -> Result { panic!() } } pub trait Dimensional: Index { } -pub struct Mat2 { x: () } -pub struct Vec2 { x: () } +pub struct Mat2 { x: T } +pub struct Vec2 { x: T } impl Dimensional> for Mat2 { } impl Index> for Mat2 { } @@ -25,9 +25,9 @@ impl Dimensional for Vec2 { } impl Index for Vec2 { } pub trait Matrix: Dimensional { - fn identity() -> Self; + fn identity(t:T) -> Self; } impl Matrix> for Mat2 { - fn identity() -> Mat2 { Mat2{ x: () } } + fn identity(t:T) -> Mat2 { Mat2{ x: t } } } diff --git a/src/test/run-pass/issue-5192.rs b/src/test/run-pass/issue-5192.rs index bb79cd4d046..a6f3771bf62 100644 --- a/src/test/run-pass/issue-5192.rs +++ b/src/test/run-pass/issue-5192.rs @@ -12,6 +12,7 @@ #![feature(box_syntax)] pub trait EventLoop { + fn dummy(&self) { } } pub struct UvEventLoop { diff --git a/src/test/run-pass/issue-5708.rs b/src/test/run-pass/issue-5708.rs index fd39bcc6b61..59bca87bed0 100644 --- a/src/test/run-pass/issue-5708.rs +++ b/src/test/run-pass/issue-5708.rs @@ -48,7 +48,9 @@ pub fn main() { // minimal -pub trait MyTrait { } +pub trait MyTrait { + fn dummy(&self, t: T) -> T { panic!() } +} pub struct MyContainer<'a, T> { foos: Vec<&'a (MyTrait+'a)> , diff --git a/src/test/run-pass/issue-6128.rs b/src/test/run-pass/issue-6128.rs index d96862b588f..1746a6281dc 100644 --- a/src/test/run-pass/issue-6128.rs +++ b/src/test/run-pass/issue-6128.rs @@ -17,6 +17,7 @@ use std::collections::HashMap; trait Graph { fn f(&self, Edge); + fn g(&self, Node); } @@ -24,6 +25,9 @@ impl Graph for HashMap { fn f(&self, _e: E) { panic!(); } + fn g(&self, _e: int) { + panic!(); + } } pub fn main() { diff --git a/src/test/run-pass/issue-6318.rs b/src/test/run-pass/issue-6318.rs index 1d8fe8bfce8..6e608d34bd5 100644 --- a/src/test/run-pass/issue-6318.rs +++ b/src/test/run-pass/issue-6318.rs @@ -15,7 +15,9 @@ pub enum Thing { A(Box) } -pub trait Foo {} +pub trait Foo { + fn dummy(&self) { } +} pub struct Struct; diff --git a/src/test/run-pass/issue-7575.rs b/src/test/run-pass/issue-7575.rs index 225213db6a4..77cfc7f0cf6 100644 --- a/src/test/run-pass/issue-7575.rs +++ b/src/test/run-pass/issue-7575.rs @@ -10,6 +10,7 @@ trait Foo { fn new() -> bool { false } + fn dummy(&self) { } } trait Bar { diff --git a/src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs b/src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs index b6dfbb1ca42..736860947f2 100644 --- a/src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs +++ b/src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs @@ -19,7 +19,10 @@ pub fn main() {} -trait A {} +trait A { + fn dummy(&self) { } +} + impl A for T {} fn owned2(a: Box) { a as Box; } diff --git a/src/test/run-pass/issue-7911.rs b/src/test/run-pass/issue-7911.rs index 86948ebcb91..3eb593708be 100644 --- a/src/test/run-pass/issue-7911.rs +++ b/src/test/run-pass/issue-7911.rs @@ -14,7 +14,9 @@ // with different mutability in macro in two methods #![allow(unused_variable)] // unused foobar_immut + foobar_mut -trait FooBar {} +trait FooBar { + fn dummy(&self) { } +} struct Bar(i32); struct Foo { bar: Bar } diff --git a/src/test/run-pass/issue-8248.rs b/src/test/run-pass/issue-8248.rs index 377b9ce262c..7bc8dbe616f 100644 --- a/src/test/run-pass/issue-8248.rs +++ b/src/test/run-pass/issue-8248.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait A {} +trait A { + fn dummy(&self) { } +} struct B; impl A for B {} diff --git a/src/test/run-pass/issue-8249.rs b/src/test/run-pass/issue-8249.rs index 44f07def531..83c9e9bf450 100644 --- a/src/test/run-pass/issue-8249.rs +++ b/src/test/run-pass/issue-8249.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait A {} +trait A { + fn dummy(&self) { } +} struct B; impl A for B {} diff --git a/src/test/run-pass/issue-9719.rs b/src/test/run-pass/issue-9719.rs index 8fc86eb49e7..aa1e65efaa4 100644 --- a/src/test/run-pass/issue-9719.rs +++ b/src/test/run-pass/issue-9719.rs @@ -13,7 +13,9 @@ mod a { A(T), } - pub trait X {} + pub trait X { + fn dummy(&self) { } + } impl X for int {} pub struct Z<'a>(Enum<&'a (X+'a)>); @@ -21,7 +23,9 @@ mod a { } mod b { - trait X {} + trait X { + fn dummy(&self) { } + } impl X for int {} struct Y<'a>{ x:Option<&'a (X+'a)>, diff --git a/src/test/run-pass/lint-cstack.rs b/src/test/run-pass/lint-cstack.rs index 2194453aac2..f180ffcd4e8 100644 --- a/src/test/run-pass/lint-cstack.rs +++ b/src/test/run-pass/lint-cstack.rs @@ -15,7 +15,7 @@ extern { } trait A { - fn foo() { + fn foo(&self) { unsafe { rust_get_test_int(); } diff --git a/src/test/run-pass/method-early-bound-lifetimes-on-self.rs b/src/test/run-pass/method-early-bound-lifetimes-on-self.rs index 25ce0d774eb..cec9753a2fe 100644 --- a/src/test/run-pass/method-early-bound-lifetimes-on-self.rs +++ b/src/test/run-pass/method-early-bound-lifetimes-on-self.rs @@ -13,7 +13,11 @@ #![allow(dead_code)] -struct Cursor<'a>; +use std::marker; + +struct Cursor<'a> { + m: marker::PhantomData<&'a ()> +} trait CursorNavigator { fn init_cursor<'a, 'b:'a>(&'a self, cursor: &mut Cursor<'b>) -> bool; @@ -28,7 +32,7 @@ impl CursorNavigator for SimpleNavigator { } fn main() { - let mut c = Cursor; + let mut c = Cursor { m: marker::PhantomData }; let n = SimpleNavigator; n.init_cursor(&mut c); } diff --git a/src/test/run-pass/method-recursive-blanket-impl.rs b/src/test/run-pass/method-recursive-blanket-impl.rs index 338bd89ab5c..15eb2ae2e4b 100644 --- a/src/test/run-pass/method-recursive-blanket-impl.rs +++ b/src/test/run-pass/method-recursive-blanket-impl.rs @@ -17,16 +17,16 @@ use std::marker::Sized; // Note: this must be generic for the problem to show up trait Foo { - fn foo(&self); + fn foo(&self, a: A); } impl Foo for [u8] { - fn foo(&self) {} + fn foo(&self, a: u8) {} } impl<'a, A, T> Foo for &'a T where T: Foo { - fn foo(&self) { - Foo::foo(*self) + fn foo(&self, a: A) { + Foo::foo(*self, a) } } diff --git a/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs b/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs index eb17aa78bd9..1164ef1a3c9 100644 --- a/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs +++ b/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs @@ -8,8 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker::MarkerTrait; -trait Serializer { +trait Serializer : MarkerTrait { } trait Serializable { diff --git a/src/test/run-pass/overloaded-autoderef-vtable.rs b/src/test/run-pass/overloaded-autoderef-vtable.rs index be2b309b821..d50f2efe0e7 100644 --- a/src/test/run-pass/overloaded-autoderef-vtable.rs +++ b/src/test/run-pass/overloaded-autoderef-vtable.rs @@ -11,7 +11,8 @@ use std::ops::Deref; struct DerefWithHelper { - helper: H + helper: H, + value: T } trait Helper { @@ -39,6 +40,7 @@ impl Foo { } pub fn main() { - let x: DerefWithHelper, Foo> = DerefWithHelper { helper: Some(Foo {x: 5}) }; + let x: DerefWithHelper, Foo> = + DerefWithHelper { helper: Some(Foo {x: 5}), value: Foo { x: 2 } }; assert!(x.foo() == 5); } diff --git a/src/test/run-pass/overloaded-calls-param-vtables.rs b/src/test/run-pass/overloaded-calls-param-vtables.rs index 2838909c1be..2ef9e08134c 100644 --- a/src/test/run-pass/overloaded-calls-param-vtables.rs +++ b/src/test/run-pass/overloaded-calls-param-vtables.rs @@ -12,10 +12,11 @@ #![feature(unboxed_closures)] +use std::marker::PhantomData; use std::ops::Fn; use std::ops::Add; -struct G; +struct G(PhantomData); impl<'a, A: Add> Fn<(A,)> for G { type Output = i32; @@ -27,5 +28,5 @@ impl<'a, A: Add> Fn<(A,)> for G { fn main() { // ICE trigger - G(1_i32); + (G(PhantomData))(1_i32); } diff --git a/src/test/run-pass/parameterized-trait-with-bounds.rs b/src/test/run-pass/parameterized-trait-with-bounds.rs index 840e58848a7..061c9168955 100644 --- a/src/test/run-pass/parameterized-trait-with-bounds.rs +++ b/src/test/run-pass/parameterized-trait-with-bounds.rs @@ -11,12 +11,12 @@ #![allow(dead_code)] -trait A {} -trait B {} -trait C<'a, U> {} +trait A { fn get(self) -> T; } +trait B { fn get(self) -> (T,U); } +trait C<'a, U> { fn get(self) -> &'a U; } mod foo { - pub trait D<'a, T> {} + pub trait D<'a, T> { fn get(self) -> &'a T; } } fn foo1(_: &(A + Send)) {} diff --git a/src/test/run-pass/privacy-ns.rs b/src/test/run-pass/privacy-ns.rs index f3380352f5f..e9b8e694d60 100644 --- a/src/test/run-pass/privacy-ns.rs +++ b/src/test/run-pass/privacy-ns.rs @@ -19,6 +19,7 @@ // public type, private value pub mod foo1 { pub trait Bar { + fn dummy(&self) { } } pub struct Baz; @@ -50,6 +51,7 @@ fn test_glob1() { // private type, public value pub mod foo2 { trait Bar { + fn dummy(&self) { } } pub struct Baz; @@ -81,6 +83,7 @@ fn test_glob2() { // public type, public value pub mod foo3 { pub trait Bar { + fn dummy(&self) { } } pub struct Baz; diff --git a/src/test/run-pass/regions-assoc-type-static-bound.rs b/src/test/run-pass/regions-assoc-type-static-bound.rs index 6b629a9035d..80ae371e509 100644 --- a/src/test/run-pass/regions-assoc-type-static-bound.rs +++ b/src/test/run-pass/regions-assoc-type-static-bound.rs @@ -11,7 +11,10 @@ // Test that the compiler considers the 'static bound declared in the // trait. Issue #20890. -trait Foo { type Value: 'static; } +trait Foo { + type Value: 'static; + fn dummy(&self) { } +} fn require_static() {} diff --git a/src/test/run-pass/regions-bound-lists-feature-gate-2.rs b/src/test/run-pass/regions-bound-lists-feature-gate-2.rs index 0a95a89d57c..a06e0f6da78 100644 --- a/src/test/run-pass/regions-bound-lists-feature-gate-2.rs +++ b/src/test/run-pass/regions-bound-lists-feature-gate-2.rs @@ -12,7 +12,9 @@ #![feature(issue_5723_bootstrap)] -trait Foo { } +trait Foo { + fn dummy(&self) { } +} fn foo<'a, 'b, 'c:'a+'b, 'd>() { } diff --git a/src/test/run-pass/regions-bound-lists-feature-gate.rs b/src/test/run-pass/regions-bound-lists-feature-gate.rs index c5baecf7272..996583dc6de 100644 --- a/src/test/run-pass/regions-bound-lists-feature-gate.rs +++ b/src/test/run-pass/regions-bound-lists-feature-gate.rs @@ -12,8 +12,9 @@ #![feature(issue_5723_bootstrap)] - -trait Foo { } +trait Foo { + fn dummy(&self) { } +} fn foo<'a>(x: Box) { } diff --git a/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs b/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs index 978383c2447..bdc0d41c94e 100644 --- a/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs +++ b/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs @@ -14,6 +14,8 @@ // lifetime parameters must be early bound in the type of the // associated item. +use std::marker; + pub enum Value<'v> { A(&'v str), B, @@ -23,7 +25,9 @@ pub trait Decoder<'v> { fn read(&mut self) -> Value<'v>; } -pub trait Decodable<'v, D: Decoder<'v>> { +pub trait Decodable<'v, D: Decoder<'v>> + : marker::PhantomFn<(), &'v int> +{ fn decode(d: &mut D) -> Self; } diff --git a/src/test/run-pass/regions-early-bound-trait-param.rs b/src/test/run-pass/regions-early-bound-trait-param.rs index 6fcfaf58a02..3f434a4838d 100644 --- a/src/test/run-pass/regions-early-bound-trait-param.rs +++ b/src/test/run-pass/regions-early-bound-trait-param.rs @@ -53,11 +53,11 @@ fn field_invoke2<'l, 'm, 'n>(x: &'n Struct2<'l,'m>) -> int { x.f.short() } -trait MakerTrait<'o> { +trait MakerTrait { fn mk() -> Self; } -fn make_val<'p, T:MakerTrait<'p>>() -> T { +fn make_val() -> T { MakerTrait::mk() } @@ -80,7 +80,7 @@ impl<'s> Trait<'s> for (int,int) { } } -impl<'t> MakerTrait<'t> for Box+'static> { +impl<'t> MakerTrait for Box+'static> { fn mk() -> Box+'static> { box() (4,5) as Box } } diff --git a/src/test/run-pass/regions-issue-21422.rs b/src/test/run-pass/regions-issue-21422.rs new file mode 100644 index 00000000000..c59bf15afc3 --- /dev/null +++ b/src/test/run-pass/regions-issue-21422.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. + +// Regression test for issue #21422, which was related to failing to +// add inference constraints that the operands of a binary operator +// should outlive the binary operation itself. + +pub struct P<'a> { + _ptr: *const &'a u8, +} + +impl <'a> PartialEq for P<'a> { + fn eq(&self, other: &P<'a>) -> bool { + (self as *const _) == (other as *const _) + } +} + +fn main() {} diff --git a/src/test/run-pass/regions-no-bound-in-argument-cleanup.rs b/src/test/run-pass/regions-no-bound-in-argument-cleanup.rs index d3464f01203..5964ac65d5f 100644 --- a/src/test/run-pass/regions-no-bound-in-argument-cleanup.rs +++ b/src/test/run-pass/regions-no-bound-in-argument-cleanup.rs @@ -10,7 +10,9 @@ #![feature(unsafe_destructor)] -pub struct Foo; +use std::marker; + +pub struct Foo(marker::PhantomData); impl Iterator for Foo { type Item = T; diff --git a/src/test/run-pass/regions-no-variance-from-fn-generics.rs b/src/test/run-pass/regions-no-variance-from-fn-generics.rs index a35ab1bfc0c..80c478afa64 100644 --- a/src/test/run-pass/regions-no-variance-from-fn-generics.rs +++ b/src/test/run-pass/regions-no-variance-from-fn-generics.rs @@ -12,7 +12,9 @@ // should not upset the variance inference for actual occurrences of // that lifetime in type expressions. -pub trait HasLife<'a> { } +pub trait HasLife<'a> { + fn dummy(&'a self) { } // just to induce a variance on 'a +} trait UseLife01 { fn refs<'a, H: HasLife<'a>>(&'a self) -> H; @@ -23,7 +25,11 @@ trait UseLife02 { } -pub trait HasType { } +pub trait HasType +{ + fn dummy(&self, t: T) -> T { panic!() } +} + trait UseLife03 { fn refs<'a, H: HasType<&'a T>>(&'a self) -> H; diff --git a/src/test/run-pass/self-impl.rs b/src/test/run-pass/self-impl.rs index 40a4dc52a70..af2b2de8ab8 100644 --- a/src/test/run-pass/self-impl.rs +++ b/src/test/run-pass/self-impl.rs @@ -29,6 +29,7 @@ pub struct Baz { trait Bar { fn bar(x: Self, y: &Self, z: Box) -> Self; + fn dummy(&self, x: X) { } } impl Bar for Box> { diff --git a/src/test/run-pass/simple-match-generic-tag.rs b/src/test/run-pass/simple-match-generic-tag.rs index 7ed8cb434ca..2217dddbd21 100644 --- a/src/test/run-pass/simple-match-generic-tag.rs +++ b/src/test/run-pass/simple-match-generic-tag.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - -enum opt { none, } +enum opt { none, some(T) } pub fn main() { let x = opt::none::; - match x { opt::none:: => { println!("hello world"); } } + match x { + opt::none:: => { println!("hello world"); } + opt::some(_) => { } + } } diff --git a/src/test/run-pass/syntax-trait-polarity.rs b/src/test/run-pass/syntax-trait-polarity.rs index 3344844d49f..340ad2a531a 100644 --- a/src/test/run-pass/syntax-trait-polarity.rs +++ b/src/test/run-pass/syntax-trait-polarity.rs @@ -10,17 +10,17 @@ #![feature(optin_builtin_traits)] -use std::marker::Send; +use std::marker::{MarkerTrait, Send}; struct TestType; impl TestType {} -trait TestTrait {} +trait TestTrait : MarkerTrait {} impl !Send for TestType {} -struct TestType2; +struct TestType2(T); impl TestType2 {} diff --git a/src/test/run-pass/trailing-comma.rs b/src/test/run-pass/trailing-comma.rs index b5ae259bc63..76c62a83e75 100644 --- a/src/test/run-pass/trailing-comma.rs +++ b/src/test/run-pass/trailing-comma.rs @@ -12,7 +12,7 @@ fn f(_: T,) {} -struct Foo; +struct Foo(T); struct Bar; @@ -34,7 +34,7 @@ pub fn main() { let [_, _, .., _,] = [1, 1, 1, 1,]; let [_, _, _.., _,] = [1, 1, 1, 1,]; - let x: Foo = Foo::; + let x: Foo = Foo::(1); Bar::f(0,); Bar.g(0,); diff --git a/src/test/run-pass/trait-bounds-basic.rs b/src/test/run-pass/trait-bounds-basic.rs index d03496403ad..ed25bf8b02e 100644 --- a/src/test/run-pass/trait-bounds-basic.rs +++ b/src/test/run-pass/trait-bounds-basic.rs @@ -9,7 +9,7 @@ // except according to those terms. -trait Foo { +trait Foo : ::std::marker::MarkerTrait { } fn b(_x: Box) { diff --git a/src/test/run-pass/trait-bounds-on-structs-and-enums.rs b/src/test/run-pass/trait-bounds-on-structs-and-enums.rs index e3234f03754..976120908b2 100644 --- a/src/test/run-pass/trait-bounds-on-structs-and-enums.rs +++ b/src/test/run-pass/trait-bounds-on-structs-and-enums.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait U {} -trait T {} +trait U : ::std::marker::MarkerTrait {} +trait T { fn get(self) -> X; } -trait S2 { +trait S2 : ::std::marker::MarkerTrait { fn m(x: Box+'static>) {} } diff --git a/src/test/run-pass/trait-bounds-recursion.rs b/src/test/run-pass/trait-bounds-recursion.rs index 49f8999cd45..7135dad7d19 100644 --- a/src/test/run-pass/trait-bounds-recursion.rs +++ b/src/test/run-pass/trait-bounds-recursion.rs @@ -10,17 +10,17 @@ trait I { fn i(&self) -> Self; } -trait A { +trait A : ::std::marker::MarkerTrait { fn id(x:T) -> T { x.i() } } -trait J { fn j(&self) -> Self; } +trait J { fn j(&self) -> T; } -trait B> { +trait B> : ::std::marker::MarkerTrait { fn id(x:T) -> T { x.j() } } -trait C { +trait C : ::std::marker::MarkerTrait { fn id>(x:T) -> T { x.j() } } diff --git a/src/test/run-pass/trait-default-method-bound-subst4.rs b/src/test/run-pass/trait-default-method-bound-subst4.rs index 3efe2507470..383849ca512 100644 --- a/src/test/run-pass/trait-default-method-bound-subst4.rs +++ b/src/test/run-pass/trait-default-method-bound-subst4.rs @@ -11,6 +11,7 @@ trait A { fn g(&self, x: uint) -> uint { x } + fn h(&self, x: T) { } } impl A for int { } diff --git a/src/test/run-pass/trait-impl.rs b/src/test/run-pass/trait-impl.rs index 16ef315c206..bd2bf430a68 100644 --- a/src/test/run-pass/trait-impl.rs +++ b/src/test/run-pass/trait-impl.rs @@ -16,7 +16,8 @@ use traitimpl::Bar; static mut COUNT: uint = 1; -trait T {} +trait T : ::std::marker::MarkerTrait { +} impl<'a> T+'a { fn foo(&self) { diff --git a/src/test/run-pass/trait-inheritance-num2.rs b/src/test/run-pass/trait-inheritance-num2.rs index 1e6e7227a06..f89eea46090 100644 --- a/src/test/run-pass/trait-inheritance-num2.rs +++ b/src/test/run-pass/trait-inheritance-num2.rs @@ -14,8 +14,7 @@ use std::cmp::{PartialEq, PartialOrd}; use std::num::NumCast; -pub trait TypeExt {} - +pub trait TypeExt : ::std::marker::MarkerTrait { } impl TypeExt for u8 {} impl TypeExt for u16 {} diff --git a/src/test/run-pass/trait-inheritance-static2.rs b/src/test/run-pass/trait-inheritance-static2.rs index 3b454aad03e..8f3b325a513 100644 --- a/src/test/run-pass/trait-inheritance-static2.rs +++ b/src/test/run-pass/trait-inheritance-static2.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub trait MyEq { } +pub trait MyEq : ::std::marker::MarkerTrait { } -pub trait MyNum { +pub trait MyNum : ::std::marker::MarkerTrait { fn from_int(int) -> Self; } diff --git a/src/test/run-pass/trait-object-generics.rs b/src/test/run-pass/trait-object-generics.rs index 76352c799a0..6f89490716f 100644 --- a/src/test/run-pass/trait-object-generics.rs +++ b/src/test/run-pass/trait-object-generics.rs @@ -13,11 +13,14 @@ #![allow(unknown_features)] #![feature(box_syntax)] +use std::marker; + pub trait Trait2 { - fn doit(&self); + fn doit(&self) -> A; } pub struct Impl { + m1: marker::PhantomData<(A1,A2,A3)>, /* * With A2 we get the ICE: * task failed at 'index out of bounds: the len is 1 but the index is 1', @@ -28,13 +31,13 @@ pub struct Impl { impl Impl { pub fn step(&self) { - self.t.doit() + self.t.doit(); } } // test for #8601 -enum Type { Constant } +enum Type { Constant(T) } trait Trait { fn method(&self,Type<(K,V)>) -> int; @@ -46,5 +49,5 @@ impl Trait for () { pub fn main() { let a = box() () as Box>; - assert_eq!(a.method(Type::Constant), 0); + assert_eq!(a.method(Type::Constant((1u8, 2u8))), 0); } diff --git a/src/test/run-pass/trait-static-method-overwriting.rs b/src/test/run-pass/trait-static-method-overwriting.rs index a8cea24db0c..10439d5c86a 100644 --- a/src/test/run-pass/trait-static-method-overwriting.rs +++ b/src/test/run-pass/trait-static-method-overwriting.rs @@ -10,7 +10,7 @@ // except according to those terms. mod base { - pub trait HasNew { + pub trait HasNew { fn new() -> Self; } @@ -18,7 +18,7 @@ mod base { dummy: (), } - impl ::base::HasNew for Foo { + impl ::base::HasNew for Foo { fn new() -> Foo { println!("Foo"); Foo { dummy: () } @@ -29,7 +29,7 @@ mod base { dummy: (), } - impl ::base::HasNew for Bar { + impl ::base::HasNew for Bar { fn new() -> Bar { println!("Bar"); Bar { dummy: () } @@ -38,6 +38,6 @@ mod base { } pub fn main() { - let _f: base::Foo = base::HasNew::::new(); - let _b: base::Bar = base::HasNew::::new(); + let _f: base::Foo = base::HasNew::new(); + let _b: base::Bar = base::HasNew::new(); } diff --git a/src/test/run-pass/unboxed-closures-infer-recursive-fn.rs b/src/test/run-pass/unboxed-closures-infer-recursive-fn.rs index 1f9b821178c..2d1ba7f39b2 100644 --- a/src/test/run-pass/unboxed-closures-infer-recursive-fn.rs +++ b/src/test/run-pass/unboxed-closures-infer-recursive-fn.rs @@ -10,7 +10,7 @@ #![feature(core,unboxed_closures)] -use std::marker::CovariantType; +use std::marker::PhantomData; // Test that we are able to infer a suitable kind for a "recursive" // closure. As far as I can tell, coding up a recursive closure @@ -20,12 +20,12 @@ use std::marker::CovariantType; struct YCombinator { func: F, - marker: CovariantType<(A,R)>, + marker: PhantomData<(A,R)>, } impl YCombinator { fn new(f: F) -> YCombinator { - YCombinator { func: f, marker: CovariantType } + YCombinator { func: f, marker: PhantomData } } } diff --git a/src/test/run-pass/unique-object-move.rs b/src/test/run-pass/unique-object-move.rs index cec523a0671..1d4eb0a7523 100644 --- a/src/test/run-pass/unique-object-move.rs +++ b/src/test/run-pass/unique-object-move.rs @@ -13,7 +13,7 @@ #![allow(unknown_features)] #![feature(box_syntax)] -pub trait EventLoop { } +pub trait EventLoop : ::std::marker::MarkerTrait { } pub struct UvEventLoop { uvio: int diff --git a/src/test/run-pass/unsized.rs b/src/test/run-pass/unsized.rs index e6dd8d46952..ae175d27b0a 100644 --- a/src/test/run-pass/unsized.rs +++ b/src/test/run-pass/unsized.rs @@ -12,17 +12,19 @@ // Test syntax checks for `?Sized` syntax. -trait T1 {} -pub trait T2 {} -trait T3 : T2 {} -trait T4 {} -trait T5 {} -trait T6 {} -trait T7 {} -trait T8 {} -trait T9 {} -struct S1; -enum E {} +use std::marker::{PhantomData, PhantomFn}; + +trait T1 : PhantomFn { } +pub trait T2 : PhantomFn { } +trait T3 : T2 + PhantomFn { } +trait T4 : PhantomFn<(Self,X)> {} +trait T5 : PhantomFn<(Self,X,Y)> {} +trait T6 : PhantomFn<(Self,X,Y)> {} +trait T7 : PhantomFn<(Self,X,Y)> {} +trait T8 : PhantomFn<(Self,X)> {} +trait T9 : PhantomFn<(Self,X)> {} +struct S1(PhantomData); +enum E { E1(PhantomData) } impl T1 for S1 {} fn f() {} type TT = T; diff --git a/src/test/run-pass/unsized2.rs b/src/test/run-pass/unsized2.rs index 285100dd719..10b2f2fb709 100644 --- a/src/test/run-pass/unsized2.rs +++ b/src/test/run-pass/unsized2.rs @@ -15,6 +15,8 @@ // Test sized-ness checking in substitution. +use std::marker; + // Unbounded. fn f1(x: &X) { f1::(x); @@ -25,7 +27,7 @@ fn f2(x: &X) { } // Bounded. -trait T {} +trait T { fn dummy(&self) { } } fn f3(x: &X) { f3::(x); } @@ -66,20 +68,24 @@ fn f7(x: &X) { } trait T4 { - fn m1(x: &T4); - fn m2(x: &T5); + fn dummy(&self) { } + fn m1(x: &T4, y: X); + fn m2(x: &T5, y: X); } trait T5 { + fn dummy(&self) { } // not an error (for now) fn m1(x: &T4); fn m2(x: &T5); } trait T6 { + fn dummy(&self) { } fn m1(x: &T4); fn m2(x: &T5); } trait T7 { + fn dummy(&self) { } // not an error (for now) fn m1(x: &T4); fn m2(x: &T5); diff --git a/src/test/run-pass/variance-intersection-of-ref-and-opt-ref.rs b/src/test/run-pass/variance-intersection-of-ref-and-opt-ref.rs new file mode 100644 index 00000000000..948d68e0ccd --- /dev/null +++ b/src/test/run-pass/variance-intersection-of-ref-and-opt-ref.rs @@ -0,0 +1,34 @@ +// 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. + +// Elaborated version of the opening example from RFC 738. This failed +// to compile before variance because invariance of `Option` prevented +// us from approximating the lifetimes of `field1` and `field2` to a +// common intersection. + +#![allow(dead_code)] + +struct List<'l> { + field1: &'l i32, + field2: Option<&'l i32>, +} + +fn foo(field1: &i32, field2: Option<&i32>) -> i32 { + let list = List { field1: field1, field2: field2 }; + *list.field1 + list.field2.cloned().unwrap_or(0) +} + +fn main() { + let x = 22; + let y = Some(3); + let z = None; + assert_eq!(foo(&x, y.as_ref()), 25); + assert_eq!(foo(&x, z.as_ref()), 22); +} diff --git a/src/test/run-pass/variance-trait-matching.rs b/src/test/run-pass/variance-trait-matching.rs new file mode 100644 index 00000000000..10441bee3cb --- /dev/null +++ b/src/test/run-pass/variance-trait-matching.rs @@ -0,0 +1,49 @@ +// 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. + +#![allow(dead_code)] + +// Get is covariant in T +trait Get { + fn get(&self) -> T; +} + +struct Cloner { + t: T +} + +impl Get for Cloner { + fn get(&self) -> T { + self.t.clone() + } +} + +fn get<'a, G>(get: &G) -> i32 + where G : Get<&'a i32> +{ + // This call only type checks if we can use `G : Get<&'a i32>` as + // evidence that `G : Get<&'b i32>` where `'a : 'b`. + pick(get, &22) +} + +fn pick<'b, G>(get: &'b G, if_odd: &'b i32) -> i32 + where G : Get<&'b i32> +{ + let v = *get.get(); + if v % 2 != 0 { v } else { *if_odd } +} + +fn main() { + let x = Cloner { t: &23 }; + let y = get(&x); + assert_eq!(y, 23); +} + + diff --git a/src/test/run-pass/variance-vec-covariant.rs b/src/test/run-pass/variance-vec-covariant.rs new file mode 100644 index 00000000000..caec6df5a4d --- /dev/null +++ b/src/test/run-pass/variance-vec-covariant.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. + +// Test that vec is now covariant in its argument type. + +#![allow(dead_code)] + +fn foo<'a,'b>(v1: Vec<&'a i32>, v2: Vec<&'b i32>) -> i32 { + bar(v1, v2).cloned().unwrap_or(0) // only type checks if we can intersect 'a and 'b +} + +fn bar<'c>(v1: Vec<&'c i32>, v2: Vec<&'c i32>) -> Option<&'c i32> { + v1.get(0).cloned().or_else(|| v2.get(0).cloned()) +} + +fn main() { + let x = 22; + let y = 44; + assert_eq!(foo(vec![&x], vec![&y]), 22); + assert_eq!(foo(vec![&y], vec![&x]), 44); +} diff --git a/src/test/run-pass/visible-private-types-feature-gate.rs b/src/test/run-pass/visible-private-types-feature-gate.rs index 9518671b479..46e93b25697 100644 --- a/src/test/run-pass/visible-private-types-feature-gate.rs +++ b/src/test/run-pass/visible-private-types-feature-gate.rs @@ -10,7 +10,7 @@ #![feature(visible_private_types)] -trait Foo {} +trait Foo { fn dummy(&self) { } } pub trait Bar : Foo {} diff --git a/src/test/run-pass/where-clause-bounds-inconsistency.rs b/src/test/run-pass/where-clause-bounds-inconsistency.rs index a1a61127f68..3374f47ed5f 100644 --- a/src/test/run-pass/where-clause-bounds-inconsistency.rs +++ b/src/test/run-pass/where-clause-bounds-inconsistency.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Bound {} +trait Bound { + fn dummy(&self) { } +} trait Trait { fn a(&self, T) where T: Bound; diff --git a/src/test/run-pass/where-clause-early-bound-lifetimes.rs b/src/test/run-pass/where-clause-early-bound-lifetimes.rs index cade99b83a2..4a149d4d3df 100644 --- a/src/test/run-pass/where-clause-early-bound-lifetimes.rs +++ b/src/test/run-pass/where-clause-early-bound-lifetimes.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait TheTrait { } +trait TheTrait { fn dummy(&self) { } } impl TheTrait for &'static int { } diff --git a/src/test/run-pass/where-clause-method-substituion.rs b/src/test/run-pass/where-clause-method-substituion.rs index b391df8500b..ecc210ea579 100644 --- a/src/test/run-pass/where-clause-method-substituion.rs +++ b/src/test/run-pass/where-clause-method-substituion.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo {} +trait Foo { fn dummy(&self, arg: T) { } } trait Bar { fn method(&self) where A: Foo; @@ -19,7 +19,7 @@ struct X; impl Foo for X {} -impl Bar for int { +impl Bar for i32 { fn method(&self) where X: Foo { } } diff --git a/src/test/run-pass/where-for-self.rs b/src/test/run-pass/where-for-self.rs index 5d426793c2e..1fd223b0dd3 100644 --- a/src/test/run-pass/where-for-self.rs +++ b/src/test/run-pass/where-for-self.rs @@ -11,13 +11,19 @@ // Test that we can quantify lifetimes outside a constraint (i.e., including // the self type) in a where clause. +use std::marker::PhantomFn; + static mut COUNT: u32 = 1; -trait Bar<'a> { +trait Bar<'a> + : PhantomFn<&'a ()> +{ fn bar(&self); } -trait Baz<'a> { +trait Baz<'a> + : PhantomFn<&'a ()> +{ fn baz(&self); }

Parser for P { type Input = (); } diff --git a/src/test/run-pass/associated-types-nested-projections.rs b/src/test/run-pass/associated-types-nested-projections.rs index e3227613159..2ee8ef0d3dd 100644 --- a/src/test/run-pass/associated-types-nested-projections.rs +++ b/src/test/run-pass/associated-types-nested-projections.rs @@ -10,11 +10,12 @@ // Test that we can resolve nested projection types. Issue #20666. +use std::marker::MarkerTrait; use std::slice; -trait Bound {} +trait Bound : MarkerTrait {} -impl<'a> Bound for &'a int {} +impl<'a> Bound for &'a i32 {} trait IntoIterator { type Iter: Iterator; diff --git a/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs b/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs index dd5814f875b..de96af83f59 100644 --- a/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs +++ b/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs @@ -13,7 +13,9 @@ #![allow(dead_code)] -pub trait Integral { +use std::marker::MarkerTrait; + +pub trait Integral : MarkerTrait { type Opposite; } @@ -27,6 +29,8 @@ impl Integral for u32 { pub trait FnLike { type R; + + fn dummy(&self, a: A) -> Self::R { loop { } } } fn foo() diff --git a/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs b/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs index 1d264655bc4..8617750ca53 100644 --- a/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs +++ b/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs @@ -11,15 +11,17 @@ // Test that we normalize associated types that appear in bounds; if // we didn't, the call to `self.split2()` fails to type check. -struct Splits<'a, T, P>; -struct SplitsN; +use std::marker::PhantomData; + +struct Splits<'a, T:'a, P>(PhantomData<(&'a T, P)>); +struct SplitsN(PhantomData); trait SliceExt2 { type Item; fn split2<'a, P>(&'a self, pred: P) -> Splits<'a, Self::Item, P> where P: FnMut(&Self::Item) -> bool; - fn splitn2<'a, P>(&'a self, n: uint, pred: P) -> SplitsN> + fn splitn2<'a, P>(&'a self, n: u32, pred: P) -> SplitsN> where P: FnMut(&Self::Item) -> bool; } @@ -30,7 +32,7 @@ impl SliceExt2 for [T] { loop {} } - fn splitn2