Change:
This compiles, despite Rc<T: !Send. I'm guessing this is because RawTable only uses K and V with marker::CovariantType, and I guess that isn't enough for the negative-impl to propagate. I haven't checked which other collections might be unsafe.
It appears that this also isn't specifically related to trait bounds: cc
Ah, yeah. RawTable contains only a , which is of course always Send/Sync. It should presumably just contain a plain and impl Send/Sync conditionally?
Or we need a more rich marker type.
may be a good replacement for the current system as it could contain a marker of and for example. For now though a manual impl of and will probably be required. Should other collections with an unsafe representation also be audited?
I can say confidently this is the only problem case in collections. It's the only collection that uses basically a pointer.
ok cool, good to know!

Discussion:
use cmp; use hash::{Hash, Hasher}; use iter::{Iterator, IteratorExt, ExactSizeIterator, count}; <del> use marker::{Copy, Sized, self}; </del> <ins> use marker::{Copy, Send, Sync, Sized, self}; </ins> use mem::{min_align_of, size_of}; use mem; use num::{Int, UnsignedInt}; use ops::{Deref, DerefMut, Drop}; use option::Option; use option::Option::{Some, None}; <del> use ptr::{Unique, PtrExt, copy_nonoverlapping_memory, zero_memory}; use ptr; </del> <ins> use ptr::{self, PtrExt, copy_nonoverlapping_memory, zero_memory}; </ins> use rt::heap::{allocate, deallocate}; use collections::hash_state::HashState;

pub struct RawTable<K, V> { capacity: uint, size:     uint, <del> hashes:   Unique<u64>, </del> <ins> hashes:   *mut u64, </ins> // 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)>, } <ins> unsafe impl<K: Send, V: Send> Send for RawTable<K, V> {} unsafe impl<K: Sync, V: Sync> Sync for RawTable<K, V> {} </ins> struct RawBucket<K, V> { hash: *mut u64, key:  *mut K,

return RawTable { size: 0, capacity: 0, <del> hashes: Unique::null(), </del> <ins> hashes: ptr::null_mut(), </ins> marker: marker::CovariantType, }; }

RawTable { capacity: capacity, size:     0, <del> hashes:   Unique(hashes), </del> <ins> hashes:   hashes, </ins> marker:   marker::CovariantType, } }

let hashes_size = self.capacity * size_of::<u64>(); let keys_size = self.capacity * size_of::<K>(); <del> let buffer = self.hashes.0 as *mut u8; </del> <ins> let buffer = self.hashes as *mut u8; </ins> let (keys_offset, vals_offset) = calculate_offsets(hashes_size, keys_size, min_align_of::<K>(), min_align_of::<V>()); unsafe { RawBucket { <del> hash: self.hashes.0, </del> <ins> hash: self.hashes, </ins> key:  buffer.offset(keys_offset as int) as *mut K, val:  buffer.offset(vals_offset as int) as *mut V }

pub fn new(capacity: uint) -> RawTable<K, V> { unsafe { let ret = RawTable::new_uninitialized(capacity); <del> zero_memory(ret.hashes.0, capacity); </del> <ins> zero_memory(ret.hashes, capacity); </ins> ret } }

RawBuckets { raw: self.first_bucket_raw(), hashes_end: unsafe { <del> self.hashes.0.offset(self.capacity as int) </del> <ins> self.hashes.offset(self.capacity as int) </ins> }, marker: marker::ContravariantLifetime, }

#[unsafe_destructor] impl<K, V> Drop for RawTable<K, V> { fn drop(&mut self) { <del> if self.hashes.0.is_null() { </del> <ins> if self.hashes.is_null() { </ins> return; } // This is done in reverse because we've likely partially taken

vals_size, min_align_of::<V>()); unsafe { <del> deallocate(self.hashes.0 as *mut u8, size, align); </del> <ins> deallocate(self.hashes as *mut u8, size, align); </ins> // Remember how everything was allocated out of one buffer // during initialization? We only need one call to free here. }

<ins> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // Regression test for HashMap only impl'ing Send/Sync if its contents do use std::collections::HashMap; use std::rc::Rc; fn foo<T: Send>() {} fn main() { foo::<HashMap<Rc<()>, Rc<()>>>(); //~^ ERROR: the trait `core::marker::Send` is not implemented for the type `alloc::rc::Rc<()>` } </ins>