Skip to content

Implement variance RFC #738 #22286

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 34 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2594d56
Introduce the new phantomdata/phantomfn markers and integrate them
nikomatsakis Feb 12, 2015
91eedfe
Report errors for type parameters that are not constrained, either by
nikomatsakis Feb 12, 2015
8c841f2
Extend coherence check to understand subtyping.
nikomatsakis Feb 12, 2015
801bc48
Rewrite `Unique<T>` so that it is covariant in T, implies `NonZero` a…
nikomatsakis Feb 12, 2015
f2529ac
Constrain operands to outlive the operation. Fixes #21422.
nikomatsakis Feb 12, 2015
c5579ca
Fallout: Port Vec to use `Unique`
nikomatsakis Feb 12, 2015
b3c00a6
Fallout: btree. Rephrase invariant lifetime in terms of PhantomData.
nikomatsakis Feb 12, 2015
68ebe64
Fallout: port btree to use Unique, some markers.
nikomatsakis Feb 12, 2015
c2891cc
Fallout: EnumSet, add Marker.
nikomatsakis Feb 12, 2015
8dbdcdb
Fallout: RingBuf, use Unique.
nikomatsakis Feb 12, 2015
2bcf3a4
Fallout: arena needs to use phantomdata since invariantlifetime is gone
nikomatsakis Feb 12, 2015
1735e41
Fallout: AtomicPtr needs phantom data to indicate that it contains an…
nikomatsakis Feb 12, 2015
d801a4d
Fallout: iter, add markers or other changes such that all type parame…
nikomatsakis Feb 12, 2015
ef42c2b
Fallout: docs, elided examples often elided too much.
nikomatsakis Feb 12, 2015
872ce47
Fallout: tests. As tests frequently elide things, lots of changes
nikomatsakis Feb 12, 2015
60f507b
Fallout: remove unused type and region parameters.
nikomatsakis Feb 12, 2015
aaf4176
Fallout: Port slice to use `PhantomData` instead of `ContravariantLif…
nikomatsakis Feb 12, 2015
2953710
Fallout: port libflate to new Unique API
nikomatsakis Feb 12, 2015
199b992
Fallout: add phantom data to librand
nikomatsakis Feb 12, 2015
62b5177
Fallout: add phantom data to the type inferencer
nikomatsakis Feb 12, 2015
1ed5842
Fallout: extend thread with phantomdata for `'a` lifetime
nikomatsakis Feb 12, 2015
9e0bb52
Fallout: add phantomdata for 'a in path
nikomatsakis Feb 12, 2015
ae7c534
Fallout: port hashmap to use Unique
nikomatsakis Feb 12, 2015
6f2a1c9
Fallout: add phantomdata to hash
nikomatsakis Feb 12, 2015
df76442
Fallout: Accepter trait needs phantomdata. This seems like it should
nikomatsakis Feb 12, 2015
d179bb5
Add regression test for #20533. Fixes #20533.
nikomatsakis Feb 13, 2015
e8cb11c
Missing test.
nikomatsakis Feb 18, 2015
a2393e6
WIP -- improve documentation on the phantom traits
nikomatsakis Feb 18, 2015
d622235
Add deprecated versions of the old markers and integrate them back in…
nikomatsakis Feb 18, 2015
74199c2
Try to write some basic docs.
nikomatsakis Feb 18, 2015
f5491e6
Stabilize Send/Sync.
nikomatsakis Feb 18, 2015
cc61f9c
Minor unused imports etc.
nikomatsakis Feb 18, 2015
9f8b9d6
Update tests to use #[feature(rustc_attrs)]
nikomatsakis Feb 18, 2015
2e482cd
Mark intentionally buggy test as ignore
nikomatsakis Feb 18, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
10 changes: 5 additions & 5 deletions src/doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ the final namespace qualifier is omitted.
Two examples of paths with type arguments:

```
# struct HashMap<K, V>;
# struct HashMap<K, V>(K,V);
# fn f() {
# fn id<T>(t: T) -> T { t }
type T = HashMap<i32,String>; // Type arguments used in a type expression
Expand Down Expand Up @@ -1603,7 +1603,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<Shape> = Box::new(mycircle) as Box<Shape>;
Expand Down Expand Up @@ -1634,8 +1634,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
Expand Down Expand Up @@ -1729,7 +1729,7 @@ type parameters taken by the trait it implements. Implementation parameters
are written after the `impl` keyword.

```
# trait Seq<T> { }
# trait Seq<T> { fn dummy(&self, _: T) { } }
impl<T> Seq<T> for Vec<T> {
/* ... */
}
Expand Down
6 changes: 4 additions & 2 deletions src/libarena/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub struct Arena<'longer_than_self> {
head: RefCell<Chunk>,
copy_head: RefCell<Chunk>,
chunks: RefCell<Vec<Chunk>>,
_invariant: marker::InvariantLifetime<'longer_than_self>,
_marker: marker::PhantomData<*mut &'longer_than_self()>,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space after lifetime name is missing ?

}

impl<'a> Arena<'a> {
Expand All @@ -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,
}
}
}
Expand Down Expand Up @@ -361,6 +361,8 @@ pub struct TypedArena<T> {
}

struct TypedArenaChunk<T> {
marker: marker::PhantomData<T>,

/// Pointer to the next arena segment.
next: *mut TypedArenaChunk<T>,

Expand Down
17 changes: 13 additions & 4 deletions src/libcollections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -560,7 +569,7 @@ mod stack {
pub struct Pusher<'id, 'a, K:'a, V:'a> {
map: &'a mut BTreeMap<K, V>,
stack: Stack<K, V>,
marker: marker::InvariantLifetime<'id>
_marker: InvariantLifetime<'id>,
}

impl<'a, K, V> PartialSearchStack<'a, K, V> {
Expand Down Expand Up @@ -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)
Expand Down
84 changes: 52 additions & 32 deletions src/libcollections/btree/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ use core::prelude::*;
use core::borrow::BorrowFrom;
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};

/// Represents the result of an Insertion: either the item fit, or the node had to split
pub enum InsertionResult<K, V> {
Expand Down Expand Up @@ -57,8 +58,8 @@ pub struct Node<K, V> {
keys: Unique<K>,
vals: Unique<V>,

// In leaf nodes, this will be null, and no space will be allocated for edges.
edges: Unique<Node<K, V>>,
// In leaf nodes, this will be None, and no space will be allocated for edges.
edges: Option<Unique<Node<K, V>>>,

// 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.
Expand Down Expand Up @@ -278,8 +279,11 @@ impl<T> Drop for RawItems<T> {
#[unsafe_destructor]
impl<K, V> Drop for Node<K, V> {
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;
}

Expand All @@ -292,7 +296,7 @@ impl<K, V> Drop for Node<K, V> {
self.destroy();
}

self.keys.ptr = ptr::null_mut();
self.keys = unsafe { Unique::new(0 as *mut K) };
}
}

Expand All @@ -308,9 +312,9 @@ impl<K, V> Node<K, V> {
let (vals_offset, edges_offset) = calculate_offsets_generic::<K, V>(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<K, V>),
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<K, V>)),
_len: 0,
_capacity: capacity,
}
Expand All @@ -326,9 +330,9 @@ impl<K, V> Node<K, V> {
let (vals_offset, _) = calculate_offsets_generic::<K, V>(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,
}
Expand All @@ -337,18 +341,18 @@ impl<K, V> Node<K, V> {
unsafe fn destroy(&mut self) {
let (alignment, size) =
calculate_allocation_generic::<K, V>(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()
})
)}
Expand All @@ -367,8 +371,12 @@ impl<K, V> Node<K, V> {
&[]
} else {
unsafe {
let data = match self.edges {
None => heap::EMPTY as *const Node<K,V>,
Some(ref p) => **p as *const Node<K,V>,
};
mem::transmute(raw::Slice {
data: self.edges.ptr,
data: data,
len: self.len() + 1
})
}
Expand Down Expand Up @@ -524,7 +532,8 @@ impl<K: Clone, V: Clone> Clone for Node<K, V> {
#[derive(Copy)]
pub struct Handle<NodeRef, Type, NodeType> {
node: NodeRef,
index: usize
index: usize,
marker: PhantomData<(Type, NodeType)>,
}

pub mod handle {
Expand All @@ -548,8 +557,8 @@ impl<K: Ord, V> Node<K, V> {
// 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 }),
}
}
}
Expand Down Expand Up @@ -586,7 +595,7 @@ impl <K, V> Node<K, V> {

/// 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
Expand Down Expand Up @@ -618,7 +627,8 @@ impl<K, V, NodeRef, Type, NodeType> Handle<NodeRef, Type, NodeType> where
pub fn as_raw(&mut self) -> Handle<*mut Node<K, V>, Type, NodeType> {
Handle {
node: &mut *self.node as *mut _,
index: self.index
index: self.index,
marker: PhantomData,
}
}
}
Expand All @@ -630,7 +640,8 @@ impl<K, V, Type, NodeType> Handle<*mut Node<K, V>, Type, NodeType> {
pub unsafe fn from_raw<'a>(&'a self) -> Handle<&'a Node<K, V>, Type, NodeType> {
Handle {
node: &*self.node,
index: self.index
index: self.index,
marker: PhantomData,
}
}

Expand All @@ -640,7 +651,8 @@ impl<K, V, Type, NodeType> Handle<*mut Node<K, V>, Type, NodeType> {
pub unsafe fn from_raw_mut<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, Type, NodeType> {
Handle {
node: &mut *self.node,
index: self.index
index: self.index,
marker: PhantomData,
}
}
}
Expand Down Expand Up @@ -688,12 +700,14 @@ impl<K, V, NodeRef: Deref<Target=Node<K, V>>, Type> Handle<NodeRef, Type, handle
if self.node.is_leaf() {
Leaf(Handle {
node: self.node,
index: self.index
index: self.index,
marker: PhantomData,
})
} else {
Internal(Handle {
node: self.node,
index: self.index
index: self.index,
marker: PhantomData,
})
}
}
Expand Down Expand Up @@ -826,7 +840,8 @@ impl<K, V, NodeRef, NodeType> Handle<NodeRef, handle::Edge, NodeType> where
unsafe fn left_kv<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::KV, NodeType> {
Handle {
node: &mut *self.node,
index: self.index - 1
index: self.index - 1,
marker: PhantomData,
}
}

Expand All @@ -836,7 +851,8 @@ impl<K, V, NodeRef, NodeType> Handle<NodeRef, handle::Edge, NodeType> where
unsafe fn right_kv<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::KV, NodeType> {
Handle {
node: &mut *self.node,
index: self.index
index: self.index,
marker: PhantomData,
}
}
}
Expand Down Expand Up @@ -876,7 +892,8 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<&'a mut Node<K, V>, handle::KV, NodeType
pub fn into_left_edge(self) -> Handle<&'a mut Node<K, V>, handle::Edge, NodeType> {
Handle {
node: &mut *self.node,
index: self.index
index: self.index,
marker: PhantomData,
}
}
}
Expand Down Expand Up @@ -926,7 +943,8 @@ impl<K, V, NodeRef, NodeType> Handle<NodeRef, handle::KV, NodeType> where
pub fn left_edge<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::Edge, NodeType> {
Handle {
node: &mut *self.node,
index: self.index
index: self.index,
marker: PhantomData,
}
}

Expand All @@ -935,7 +953,8 @@ impl<K, V, NodeRef, NodeType> Handle<NodeRef, handle::KV, NodeType> where
pub fn right_edge<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::Edge, NodeType> {
Handle {
node: &mut *self.node,
index: self.index + 1
index: self.index + 1,
marker: PhantomData,
}
}
}
Expand Down Expand Up @@ -1044,7 +1063,8 @@ impl<K, V> Node<K, V> {
debug_assert!(index < self.len(), "kv_handle index out of bounds");
Handle {
node: self,
index: index
index: index,
marker: PhantomData,
}
}

Expand All @@ -1064,7 +1084,7 @@ impl<K, V> Node<K, V> {
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()
},
Expand Down
Loading