Skip to content

Commit

Permalink
Auto merge of #21689 - FlaPer87:oibit-send-and-friends, r=nikomatsakis
Browse files Browse the repository at this point in the history
This is one more step towards completing #13231

This series of commits add support for default trait implementations. The changes in this PR don't break existing code and they are expected to preserve the existing behavior in the compiler as far as built-in bounds checks go.

The PR adds negative implementations of `Send`/`Sync` for some types and it removes the special cases for `Send`/`Sync` during the trait obligations checks. That is, it now fully relies on the traits check rather than lang items.

Once this patch lands and a new snapshot is created, it'll be possible to add default impls for `Send` and `Sync` and remove entirely the use of `BuiltinBound::{BoundSend,BoundSync}` for positive implementations as well.

This PR also removes the restriction on negative implementations. That is, it is now possible to add negative implementations for traits other than `Send`/`Sync`
  • Loading branch information
bors committed Feb 23, 2015
2 parents f0f7ca2 + 3dcc631 commit dc6e06e
Show file tree
Hide file tree
Showing 68 changed files with 1,208 additions and 176 deletions.
4 changes: 3 additions & 1 deletion src/libcore/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@
use clone::Clone;
use cmp::PartialEq;
use default::Default;
use marker::{Copy, Send};
use marker::{Copy, Send, Sync};
use ops::{Deref, DerefMut, Drop};
use option::Option;
use option::Option::{None, Some};
Expand Down Expand Up @@ -660,6 +660,8 @@ pub struct UnsafeCell<T> {
pub value: T,
}

impl<T> !Sync for UnsafeCell<T> {}

impl<T> UnsafeCell<T> {
/// Construct a new instance of `UnsafeCell` which will wrap the specified
/// value.
Expand Down
1 change: 1 addition & 0 deletions src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(rustc_attrs)]
#![feature(optin_builtin_traits)]

#[macro_use]
mod macros;
Expand Down
8 changes: 8 additions & 0 deletions src/libcore/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ pub unsafe trait Send : MarkerTrait {
// empty.
}

impl<T> !Send for *const T { }
impl<T> !Send for *mut T { }
impl !Send for Managed { }

/// Types with a constant size known at compile-time.
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="sized"]
Expand Down Expand Up @@ -204,6 +208,10 @@ pub unsafe trait Sync : MarkerTrait {
// Empty
}

impl<T> !Sync for *const T { }
impl<T> !Sync for *mut T { }
impl !Sync for Managed { }

/// 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.
Expand Down
4 changes: 4 additions & 0 deletions src/librustc/metadata/csearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,3 +410,7 @@ pub fn is_associated_type(cstore: &cstore::CStore, def: ast::DefId) -> bool {
decoder::is_associated_type(&*cdata, def.node)
}

pub fn is_default_trait(cstore: &cstore::CStore, def: ast::DefId) -> bool {
let cdata = cstore.get_crate_data(def.krate);
decoder::is_default_trait(&*cdata, def.node)
}
19 changes: 15 additions & 4 deletions src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ enum Family {
TupleVariant, // v
StructVariant, // V
Impl, // i
DefaultImpl, // d
Trait, // I
Struct, // S
PublicField, // g
Expand All @@ -151,6 +152,7 @@ fn item_family(item: rbml::Doc) -> Family {
'v' => TupleVariant,
'V' => StructVariant,
'i' => Impl,
'd' => DefaultImpl,
'I' => Trait,
'S' => Struct,
'g' => PublicField,
Expand Down Expand Up @@ -355,9 +357,9 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
let enum_did = item_reqd_and_translated_parent_item(cnum, item);
DlDef(def::DefVariant(enum_did, did, false))
}
Trait => DlDef(def::DefTrait(did)),
Trait => DlDef(def::DefaultImpl(did)),
Enum => DlDef(def::DefTy(did, true)),
Impl => DlImpl(did),
Impl | DefaultImpl => DlImpl(did),
PublicField | InheritedField => DlField,
}
}
Expand Down Expand Up @@ -480,7 +482,7 @@ pub fn get_impl_trait<'tcx>(cdata: Cmd,
let item_doc = lookup_item(id, cdata.data());
let fam = item_family(item_doc);
match fam {
Family::Impl => {
Family::Impl | Family::DefaultImpl => {
reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| {
doc_trait_ref(tp, tcx, cdata)
})
Expand Down Expand Up @@ -1356,7 +1358,7 @@ pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
let parent_item_doc = lookup_item(parent_item_id.node, cdata.data());
match item_family(parent_item_doc) {
Trait => Some(item_def_id(parent_item_doc, cdata)),
Impl => {
Impl | DefaultImpl => {
reader::maybe_get_doc(parent_item_doc, tag_item_trait_ref)
.map(|_| item_trait_ref(parent_item_doc, tcx, cdata).def_id)
}
Expand Down Expand Up @@ -1561,3 +1563,12 @@ pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool {
Some(item) => item_sort(item) == 't',
}
}


pub fn is_default_trait<'tcx>(cdata: Cmd, id: ast::NodeId) -> bool {
let item_doc = lookup_item(id, cdata.data());
match item_family(item_doc) {
Family::DefaultImpl => true,
_ => false
}
}
12 changes: 12 additions & 0 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1201,6 +1201,18 @@ fn encode_info_for_item(ecx: &EncodeContext,
None => {}
}
}
ast::ItemDefaultImpl(unsafety, ref ast_trait_ref) => {
add_to_index(item, rbml_w, index);
rbml_w.start_tag(tag_items_data_item);
encode_def_id(rbml_w, def_id);
encode_family(rbml_w, 'd');
encode_name(rbml_w, item.ident.name);
encode_unsafety(rbml_w, unsafety);

let trait_ref = ty::node_id_to_trait_ref(tcx, ast_trait_ref.ref_id);
encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref);
rbml_w.end_tag();
}
ast::ItemImpl(unsafety, polarity, _, ref opt_trait, ref ty, ref ast_items) => {
// We need to encode information about the default methods we
// have inherited, so we drive this based on the impl structure.
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ impl tr for def::Def {
def::DefVariant(e_did, v_did, is_s) => {
def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s)
},
def::DefTrait(did) => def::DefTrait(did.tr(dcx)),
def::DefaultImpl(did) => def::DefaultImpl(did.tr(dcx)),
def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum),
def::DefAssociatedTy(did) => def::DefAssociatedTy(did.tr(dcx)),
def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did), ident) =>
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub enum Def {
// type `U` (indicated by the Ident).
// FIXME(#20301) -- should use Name
DefAssociatedPath(TyParamProvenance, ast::Ident),
DefTrait(ast::DefId),
DefaultImpl(ast::DefId),
DefPrimTy(ast::PrimTy),
DefTyParam(ParamSpace, u32, ast::DefId, ast::Name),
DefUse(ast::DefId),
Expand Down Expand Up @@ -135,7 +135,7 @@ impl Def {
DefFn(id, _) | DefStaticMethod(id, _) | DefMod(id) |
DefForeignMod(id) | DefStatic(id, _) |
DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(id) |
DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) |
DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefaultImpl(id) |
DefMethod(id, _, _) | DefConst(id) |
DefAssociatedPath(TyParamProvenance::FromSelf(id), _) |
DefAssociatedPath(TyParamProvenance::FromParam(id), _) => {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
Ok(self.cat_rvalue_node(id, span, expr_ty))
}
def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
def::DefaultImpl(_) | def::DefTy(..) | def::DefPrimTy(_) |
def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) |
def::DefLabel(_) | def::DefSelfTy(..) |
def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> {
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/middle/reachable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
ast::ItemTy(..) | ast::ItemStatic(_, _, _) |
ast::ItemMod(..) | ast::ItemForeignMod(..) |
ast::ItemImpl(..) | ast::ItemTrait(..) |
ast::ItemStruct(..) | ast::ItemEnum(..) => {}
ast::ItemStruct(..) | ast::ItemEnum(..) |
ast::ItemDefaultImpl(..) => {}

_ => {
self.tcx.sess.span_bug(item.span,
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
ast::ItemUse(_) |
ast::ItemMod(..) |
ast::ItemMac(..) |
ast::ItemDefaultImpl(..) |
ast::ItemForeignMod(..) |
ast::ItemStatic(..) |
ast::ItemConst(..) => {
Expand Down Expand Up @@ -168,7 +169,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
// if this path references a trait, then this will resolve to
// a trait ref, which introduces a binding scope.
match self.def_map.borrow().get(&id) {
Some(&def::DefTrait(..)) => {
Some(&def::DefaultImpl(..)) => {
self.with(LateScope(&Vec::new(), self.scope), |_, this| {
this.visit_path(path, id);
});
Expand Down
45 changes: 42 additions & 3 deletions src/librustc/middle/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,12 @@ pub enum Vtable<'tcx, N> {
/// Vtable identifying a particular impl.
VtableImpl(VtableImplData<'tcx, N>),

/// Vtable for default trait implementations
/// This carries the information and nested obligations with regards
/// to a default implementation for a trait `Trait`. The nested obligations
/// ensure the trait implementation holds for all the constituent types.
VtableDefaultImpl(VtableDefaultImplData<N>),

/// Successful resolution to an obligation provided by the caller
/// for some type parameter. The `Vec<N>` represents the
/// obligations incurred from normalizing the where-clause (if
Expand Down Expand Up @@ -259,6 +265,12 @@ pub struct VtableImplData<'tcx, N> {
pub nested: subst::VecPerParamSpace<N>
}

#[derive(Debug,Clone)]
pub struct VtableDefaultImplData<N> {
pub trait_def_id: ast::DefId,
pub nested: Vec<N>
}

#[derive(Debug,Clone)]
pub struct VtableBuiltinData<N> {
pub nested: subst::VecPerParamSpace<N>
Expand Down Expand Up @@ -513,17 +525,18 @@ impl<'tcx, N> Vtable<'tcx, N> {
pub fn iter_nested(&self) -> Iter<N> {
match *self {
VtableImpl(ref i) => i.iter_nested(),
VtableFnPointer(..) => (&[]).iter(),
VtableClosure(..) => (&[]).iter(),
VtableParam(ref n) => n.iter(),
VtableObject(_) => (&[]).iter(),
VtableBuiltin(ref i) => i.iter_nested(),
VtableObject(_) |
VtableDefaultImpl(..) | VtableFnPointer(..) |
VtableClosure(..) => (&[]).iter(),
}
}

pub fn map_nested<M, F>(&self, op: F) -> Vtable<'tcx, M> where F: FnMut(&N) -> M {
match *self {
VtableImpl(ref i) => VtableImpl(i.map_nested(op)),
VtableDefaultImpl(ref t) => VtableDefaultImpl(t.map_nested(op)),
VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()),
VtableClosure(d, ref s) => VtableClosure(d, s.clone()),
VtableParam(ref n) => VtableParam(n.iter().map(op).collect()),
Expand All @@ -539,6 +552,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
VtableImpl(i) => VtableImpl(i.map_move_nested(op)),
VtableFnPointer(sig) => VtableFnPointer(sig),
VtableClosure(d, s) => VtableClosure(d, s),
VtableDefaultImpl(t) => VtableDefaultImpl(t.map_move_nested(op)),
VtableParam(n) => VtableParam(n.into_iter().map(op).collect()),
VtableObject(p) => VtableObject(p),
VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)),
Expand Down Expand Up @@ -573,6 +587,31 @@ impl<'tcx, N> VtableImplData<'tcx, N> {
}
}

impl<N> VtableDefaultImplData<N> {
pub fn iter_nested(&self) -> Iter<N> {
self.nested.iter()
}

pub fn map_nested<M, F>(&self, op: F) -> VtableDefaultImplData<M> where
F: FnMut(&N) -> M,
{
VtableDefaultImplData {
trait_def_id: self.trait_def_id,
nested: self.nested.iter().map(op).collect()
}
}

pub fn map_move_nested<M, F>(self, op: F) -> VtableDefaultImplData<M> where
F: FnMut(N) -> M,
{
let VtableDefaultImplData { trait_def_id, nested } = self;
VtableDefaultImplData {
trait_def_id: trait_def_id,
nested: nested.into_iter().map(op).collect()
}
}
}

impl<N> VtableBuiltinData<N> {
pub fn iter_nested(&self) -> Iter<N> {
self.nested.iter()
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
// projection. And the projection where clause is handled
// in `assemble_candidates_from_param_env`.
}
super::VtableDefaultImpl(..) |
super::VtableBuiltin(..) => {
// These traits have no associated types.
selcx.tcx().sess.span_bug(
Expand Down
Loading

0 comments on commit dc6e06e

Please sign in to comment.