Auto merge of - FlaPer87:oibit-send-and-friends, r=nikomatsakis

This is one more step towards completing 

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`
This commit is contained in:
bors 2015-02-24 02:22:44 +00:00
commit 2890508d97
68 changed files with 1210 additions and 178 deletions

@ -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};
@ -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.

@ -68,6 +68,7 @@
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(rustc_attrs)]
#![feature(optin_builtin_traits)]
#[macro_use]
mod macros;

@ -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"]
@ -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.

@ -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)
}

@ -126,6 +126,7 @@ enum Family {
TupleVariant, // v
StructVariant, // V
Impl, // i
DefaultImpl, // d
Trait, // I
Struct, // S
PublicField, // g
@ -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,
@ -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,
}
}
@ -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)
})
@ -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)
}
@ -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
}
}

@ -1193,6 +1193,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.

@ -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) =>

@ -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),
@ -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), _) => {

@ -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(..)=> {

@ -290,7 +290,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,

@ -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(..) => {
@ -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);
});

@ -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
@ -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>
@ -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()),
@ -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)),
@ -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()

@ -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(

@ -17,17 +17,17 @@ use self::SelectionCandidate::*;
use self::BuiltinBoundConditions::*;
use self::EvaluationResult::*;
use super::{DerivedObligationCause};
use super::{project};
use super::project::Normalized;
use super::DerivedObligationCause;
use super::project;
use super::project::{normalize_with_depth, Normalized};
use super::{PredicateObligation, TraitObligation, ObligationCause};
use super::{ObligationCauseCode, BuiltinDerivedObligation};
use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation};
use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
use super::{Selection};
use super::{SelectionResult};
use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
VtableFnPointer, VtableObject};
use super::{VtableImplData, VtableObjectData, VtableBuiltinData};
VtableFnPointer, VtableObject, VtableDefaultImpl};
use super::{VtableImplData, VtableObjectData, VtableBuiltinData, VtableDefaultImplData};
use super::object_safety;
use super::{util};
@ -136,6 +136,7 @@ enum SelectionCandidate<'tcx> {
BuiltinCandidate(ty::BuiltinBound),
ParamCandidate(ty::PolyTraitRef<'tcx>),
ImplCandidate(ast::DefId),
DefaultImplCandidate(ast::DefId),
/// This is a trait matching with a projected type as `Self`, and
/// we found an applicable bound in the trait definition.
@ -151,6 +152,8 @@ enum SelectionCandidate<'tcx> {
ObjectCandidate,
BuiltinObjectCandidate,
ErrorCandidate,
}
@ -818,31 +821,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!("obligation self ty is {}",
obligation.predicate.0.self_ty().repr(self.tcx()));
// User-defined copy impls are permitted, but only for
// structs and enums.
try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
// For other types, we'll use the builtin rules.
try!(self.assemble_builtin_bound_candidates(ty::BoundCopy,
stack,
&mut candidates));
}
Some(bound @ ty::BoundSend) |
Some(bound @ ty::BoundSync) => {
try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
// No explicit impls were declared for this type, consider the fallback rules.
if candidates.vec.is_empty() && !candidates.ambiguous {
try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates));
}
}
Some(bound @ ty::BoundSized) => {
// Sized and Copy are always automatically computed.
// Sized is never implementable by end-users, it is
// always automatically computed.
try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates));
}
Some(ty::BoundSend) |
Some(ty::BoundSync) |
None => {
// For the time being, we ignore user-defined impls for builtin-bounds, other than
// `Copy`.
// (And unboxed candidates only apply to the Fn/FnMut/etc traits.)
try!(self.assemble_closure_candidates(obligation, &mut candidates));
try!(self.assemble_fn_pointer_candidates(obligation, &mut candidates));
try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
@ -852,6 +848,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
try!(self.assemble_candidates_from_caller_bounds(stack, &mut candidates));
// Default implementations have lower priority, so we only
// consider triggering a default if there is no other impl that can apply.
if candidates.vec.len() == 0 {
try!(self.assemble_candidates_from_default_impls(obligation, &mut candidates));
}
debug!("candidate list size: {}", candidates.vec.len());
Ok(candidates)
}
@ -1131,7 +1132,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
debug!("assemble_candidates_from_impls(self_ty={})", self_ty.repr(self.tcx()));
let all_impls = self.all_impls(obligation.predicate.def_id());
let def_id = obligation.predicate.def_id();
let all_impls = self.all_impls(def_id);
for &impl_def_id in &all_impls {
self.infcx.probe(|snapshot| {
let (skol_obligation_trait_pred, skol_map) =
@ -1145,6 +1147,65 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
});
}
Ok(())
}
fn assemble_candidates_from_default_impls(&mut self,
obligation: &TraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>)
-> Result<(), SelectionError<'tcx>>
{
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
debug!("assemble_candidates_from_default_impls(self_ty={})", self_ty.repr(self.tcx()));
let def_id = obligation.predicate.def_id();
if ty::trait_has_default_impl(self.tcx(), def_id) {
match self_ty.sty {
ty::ty_trait(..) |
ty::ty_param(..) |
ty::ty_projection(..) => {
// In these cases, we don't know what the actual
// type is. Therefore, we cannot break it down
// into its constituent types. So we don't
// consider the `..` impl but instead just add no
// candidates: this means that typeck will only
// succeed if there is another reason to believe
// that this obligation holds. That could be a
// where-clause or, in the case of an object type,
// it could be that the object type lists the
// trait (e.g. `Foo+Send : Send`). See
// `compile-fail/typeck-default-trait-impl-send-param.rs`
// for an example of a test case that exercises
// this path.
}
ty::ty_infer(ty::TyVar(_)) => {
// the defaulted impl might apply, we don't know
candidates.ambiguous = true;
}
_ => {
if self.constituent_types_for_ty(self_ty).is_some() {
candidates.vec.push(DefaultImplCandidate(def_id.clone()))
} else {
// We don't yet know what the constituent
// types are. So call it ambiguous for now,
// though this is a bit stronger than
// necessary: that is, we know that the
// defaulted impl applies, but we can't
// process the confirmation step without
// knowing the constituent types. (Anyway, in
// the particular case of defaulted impls, it
// doesn't really matter much either way,
// since we won't be aiding inference by
// processing the confirmation step.)
candidates.ambiguous = true;
}
}
}
}
Ok(())
}
@ -1171,6 +1232,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let poly_trait_ref = match self_ty.sty {
ty::ty_trait(ref data) => {
match self.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) {
Some(bound @ ty::BoundSend) | Some(bound @ ty::BoundSync) => {
if data.bounds.builtin_bounds.contains(&bound) {
debug!("assemble_candidates_from_object_ty: matched builtin bound, \
pushing candidate");
candidates.vec.push(BuiltinObjectCandidate);
return;
}
}
_ => {}
}
data.principal_trait_ref_with_self_ty(self.tcx(), self_ty)
}
ty::ty_infer(ty::TyVar(_)) => {
@ -1258,6 +1331,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
(&ImplCandidate(..), &ParamCandidate(..)) |
(&ClosureCandidate(..), &ParamCandidate(..)) |
(&FnPointerCandidate(..), &ParamCandidate(..)) |
(&BuiltinObjectCandidate(..), &ParamCandidate(_)) |
(&BuiltinCandidate(..), &ParamCandidate(..)) => {
// We basically prefer always prefer to use a
// where-clause over another option. Where clauses
@ -1267,6 +1341,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// #18453.
true
}
(&DefaultImplCandidate(_), _) => {
// Prefer other candidates over default implementations.
self.tcx().sess.bug(
"default implementations shouldn't be recorded \
when there are other valid candidates");
}
(&ProjectionCandidate, &ParamCandidate(_)) => {
// FIXME(#20297) -- this gives where clauses precedent
// over projections. Really these are just two means
@ -1341,7 +1421,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(If(Vec::new()))
}
ty::ty_uniq(referent_ty) => { // Box<T>
ty::ty_uniq(_) => { // Box<T>
match bound {
ty::BoundCopy => {
Err(Unimplemented)
@ -1351,24 +1431,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(If(Vec::new()))
}
ty::BoundSync |
ty::BoundSend => {
Ok(If(vec![referent_ty]))
ty::BoundSync | ty::BoundSend => {
self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
}
}
}
ty::ty_ptr(..) => { // *const T, *mut T
match bound {
ty::BoundCopy |
ty::BoundSized => {
ty::BoundCopy | ty::BoundSized => {
Ok(If(Vec::new()))
}
ty::BoundSync |
ty::BoundSend => {
// sync and send are not implemented for *const, *mut
Err(Unimplemented)
ty::BoundSync | ty::BoundSend => {
self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
}
}
}
@ -1378,7 +1454,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::BoundSized => {
Err(Unimplemented)
}
ty::BoundCopy | ty::BoundSync | ty::BoundSend => {
ty::BoundCopy => {
if data.bounds.builtin_bounds.contains(&bound) {
Ok(If(Vec::new()))
} else {
@ -1397,10 +1473,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Err(Unimplemented)
}
}
ty::BoundSync | ty::BoundSend => {
self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
}
}
}
ty::ty_rptr(_, ty::mt { ty: referent_ty, mutbl }) => {
ty::ty_rptr(_, ty::mt { ty: _, mutbl }) => {
// &mut T or &T
match bound {
ty::BoundCopy => {
@ -1421,9 +1500,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(If(Vec::new()))
}
ty::BoundSync |
ty::BoundSend => {
Ok(If(vec![referent_ty]))
ty::BoundSync | ty::BoundSend => {
self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
}
}
}
@ -1452,9 +1530,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
ty::BoundSync |
ty::BoundSend => {
Ok(If(vec![element_ty]))
ty::BoundSync | ty::BoundSend => {
self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
}
}
}
@ -1462,13 +1539,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::ty_str => {
// Equivalent to [u8]
match bound {
ty::BoundSync |
ty::BoundSend => {
Ok(If(Vec::new()))
ty::BoundSync | ty::BoundSend => {
self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
}
ty::BoundCopy |
ty::BoundSized => {
ty::BoundCopy | ty::BoundSized => {
Err(Unimplemented)
}
}
@ -1521,7 +1596,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::struct_fields(self.tcx(), def_id, substs).iter()
.map(|f| f.mt.ty)
.collect();
nominal(self, bound, def_id, types)
nominal(bound, types)
}
ty::ty_enum(def_id, substs) => {
@ -1531,7 +1606,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.flat_map(|variant| variant.args.iter())
.cloned()
.collect();
nominal(self, bound, def_id, types)
nominal(bound, types)
}
ty::ty_projection(_) |
@ -1556,15 +1631,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// "opened" unsized/existential type (one that has
// been dereferenced)
match bound {
ty::BoundCopy |
ty::BoundSync |
ty::BoundSend => {
ty::BoundCopy => {
Ok(If(vec!(ty)))
}
ty::BoundSized => {
Err(Unimplemented)
}
ty::BoundSync |
ty::BoundSend => {
self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
}
}
}
ty::ty_err => {
@ -1580,38 +1658,108 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
};
fn nominal<'cx, 'tcx>(this: &mut SelectionContext<'cx, 'tcx>,
bound: ty::BuiltinBound,
def_id: ast::DefId,
fn nominal<'cx, 'tcx>(bound: ty::BuiltinBound,
types: Vec<Ty<'tcx>>)
-> Result<BuiltinBoundConditions<'tcx>,SelectionError<'tcx>>
{
// First check for markers and other nonsense.
let tcx = this.tcx();
match bound {
ty::BoundSend => {
if Some(def_id) == tcx.lang_items.managed_bound() {
return Err(Unimplemented)
}
}
// Fallback to whatever user-defined impls exist in this case.
ty::BoundCopy => Ok(ParameterBuiltin),
ty::BoundCopy => {
return Ok(ParameterBuiltin)
}
// Sized if all the component types are sized.
ty::BoundSized => Ok(If(types)),
ty::BoundSync => {
if
Some(def_id) == tcx.lang_items.managed_bound() ||
Some(def_id) == tcx.lang_items.unsafe_cell_type()
{
return Err(Unimplemented)
}
}
// Shouldn't be coming through here.
ty::BoundSend | ty::BoundSync => unreachable!(),
}
}
}
ty::BoundSized => { }
/// For default impls, we need to break apart a type into its
/// "constituent types" -- meaning, the types that it contains.
///
/// Here are some (simple) examples:
///
/// ```
/// (i32, u32) -> [i32, u32]
/// Foo where struct Foo { x: i32, y: u32 } -> [i32, u32]
/// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32]
/// Zed<i32> where enum Zed { A(T), B(u32) } -> [i32, u32]
/// ```
fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Option<Vec<Ty<'tcx>>> {
match t.sty {
ty::ty_uint(_) |
ty::ty_int(_) |
ty::ty_bool |
ty::ty_float(_) |
ty::ty_bare_fn(..) |
ty::ty_str |
ty::ty_err |
ty::ty_infer(ty::IntVar(_)) |
ty::ty_infer(ty::FloatVar(_)) |
ty::ty_char => {
Some(Vec::new())
}
Ok(If(types))
ty::ty_trait(..) |
ty::ty_param(..) |
ty::ty_projection(..) |
ty::ty_infer(ty::TyVar(_)) |
ty::ty_infer(ty::FreshTy(_)) |
ty::ty_infer(ty::FreshIntTy(_)) => {
self.tcx().sess.bug(
&format!(
"asked to assemble constituent types of unexpected type: {}",
t.repr(self.tcx()))[]);
}
ty::ty_uniq(referent_ty) => { // Box<T>
Some(vec![referent_ty])
}
ty::ty_open(element_ty) => {Some(vec![element_ty])},
ty::ty_ptr(ty::mt { ty: element_ty, ..}) |
ty::ty_rptr(_, ty::mt { ty: element_ty, ..}) => {
Some(vec![element_ty])
},
ty::ty_vec(element_ty, _) => {
Some(vec![element_ty])
}
ty::ty_tup(ref tys) => {
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
Some(tys.clone())
}
ty::ty_closure(def_id, _, substs) => {
assert_eq!(def_id.krate, ast::LOCAL_CRATE);
match self.closure_typer.closure_upvars(def_id, substs) {
Some(upvars) => {
Some(upvars.iter().map(|c| c.ty).collect())
}
None => {
None
}
}
}
ty::ty_struct(def_id, substs) => {
Some(ty::struct_fields(self.tcx(), def_id, substs).iter()
.map(|f| f.mt.ty)
.collect())
}
ty::ty_enum(def_id, substs) => {
Some(ty::substd_enum_variants(self.tcx(), def_id, substs)
.iter()
.flat_map(|variant| variant.args.iter())
.map(|&ty| ty)
.collect())
}
}
}
@ -1647,6 +1795,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(VtableParam(obligations))
}
DefaultImplCandidate(trait_def_id) => {
let data = try!(self.confirm_default_impl_candidate(obligation, trait_def_id));
Ok(VtableDefaultImpl(data))
}
ImplCandidate(impl_def_id) => {
let vtable_impl =
try!(self.confirm_impl_candidate(obligation, impl_def_id));
@ -1658,6 +1811,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(VtableClosure(closure_def_id, substs))
}
BuiltinObjectCandidate => {
// This indicates something like `(Trait+Send) :
// Send`. In this case, we know that this holds
// because that's what the object type is telling us,
// and there's really no additional obligations to
// prove and no types in particular to unify etc.
Ok(VtableParam(Vec::new()))
}
ObjectCandidate => {
let data = self.confirm_object_candidate(obligation);
Ok(VtableObject(data))
@ -1779,6 +1941,99 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
VtableBuiltinData { nested: obligations }
}
/// This handles the case where a `impl Foo for ..` impl is being used.
/// The idea is that the impl applies to `X : Foo` if the following conditions are met:
///
/// 1. For each constituent type `Y` in `X`, `Y : Foo` holds
/// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds.
fn confirm_default_impl_candidate(&mut self,
obligation: &TraitObligation<'tcx>,
impl_def_id: ast::DefId)
-> Result<VtableDefaultImplData<PredicateObligation<'tcx>>,
SelectionError<'tcx>>
{
debug!("confirm_default_impl_candidate({}, {})",
obligation.repr(self.tcx()),
impl_def_id.repr(self.tcx()));
let self_ty = self.infcx.shallow_resolve(obligation.predicate.0.self_ty());
match self.constituent_types_for_ty(self_ty) {
Some(types) => {
Ok(self.vtable_default_impl(obligation, impl_def_id, types))
}
None => {
self.tcx().sess.bug(
&format!(
"asked to confirm default implementation for ambiguous type: {}",
self_ty.repr(self.tcx()))[]);
}
}
}
/// See `confirm_default_impl_candidate`
fn vtable_default_impl(&mut self,
obligation: &TraitObligation<'tcx>,
trait_def_id: ast::DefId,
nested: Vec<Ty<'tcx>>)
-> VtableDefaultImplData<PredicateObligation<'tcx>>
{
let derived_cause = self.derived_cause(obligation, ImplDerivedObligation);
let obligations = nested.iter().map(|&nested_ty| {
// the obligation might be higher-ranked, e.g. for<'a> &'a
// int : Copy. In that case, we will wind up with
// late-bound regions in the `nested` vector. So for each
// one we instantiate to a skolemized region, do our work
// to produce something like `&'0 int : Copy`, and then
// re-bind it. This is a bit of busy-work but preserves
// the invariant that we only manipulate free regions, not
// bound ones.
self.infcx.try(|snapshot| {
let (skol_ty, skol_map) =
self.infcx().skolemize_late_bound_regions(&ty::Binder(nested_ty), snapshot);
let skol_predicate =
util::predicate_for_default_trait_impl(
self.tcx(),
derived_cause.clone(),
trait_def_id,
obligation.recursion_depth + 1,
skol_ty);
match skol_predicate {
Ok(skol_predicate) => Ok(self.infcx().plug_leaks(skol_map, snapshot,
&skol_predicate)),
Err(ErrorReported) => Err(ErrorReported)
}
})
}).collect::<Result<_, _>>();
let mut obligations = match obligations {
Ok(o) => o,
Err(ErrorReported) => Vec::new()
};
let _: Result<(),()> = self.infcx.try(|snapshot| {
let (_, skol_map) =
self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
let substs = obligation.predicate.to_poly_trait_ref().substs();
let trait_obligations = self.impl_or_trait_obligations(obligation.cause.clone(),
obligation.recursion_depth + 1,
trait_def_id,
substs,
skol_map,
snapshot);
obligations.push_all(trait_obligations.as_slice());
Ok(())
});
debug!("vtable_default_impl_data: obligations={}", obligations.repr(self.tcx()));
VtableDefaultImplData {
trait_def_id: trait_def_id,
nested: obligations
}
}
fn confirm_impl_candidate(&mut self,
obligation: &TraitObligation<'tcx>,
impl_def_id: ast::DefId)
@ -1819,12 +2074,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
skol_map.repr(self.tcx()));
let mut impl_obligations =
self.impl_obligations(cause,
recursion_depth,
impl_def_id,
&substs.value,
skol_map,
snapshot);
self.impl_or_trait_obligations(cause,
recursion_depth,
impl_def_id,
&substs.value,
skol_map,
snapshot);
debug!("vtable_impl: impl_def_id={} impl_obligations={}",
impl_def_id.repr(self.tcx()),
@ -2244,28 +2499,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::Binder(trait_ref)
}
fn impl_obligations(&mut self,
cause: ObligationCause<'tcx>,
recursion_depth: uint,
impl_def_id: ast::DefId,
impl_substs: &Substs<'tcx>,
skol_map: infer::SkolemizationMap,
snapshot: &infer::CombinedSnapshot)
-> VecPerParamSpace<PredicateObligation<'tcx>>
/// Returns the obligations that are implied by instantiating an
/// impl or trait. The obligations are substituted and fully
/// normalized. This is used when confirming an impl or default
/// impl.
fn impl_or_trait_obligations(&mut self,
cause: ObligationCause<'tcx>,
recursion_depth: uint,
def_id: ast::DefId, // of impl or trait
substs: &Substs<'tcx>, // for impl or trait
skol_map: infer::SkolemizationMap,
snapshot: &infer::CombinedSnapshot)
-> VecPerParamSpace<PredicateObligation<'tcx>>
{
let impl_bounds = ty::lookup_predicates(self.tcx(), impl_def_id);
let bounds = impl_bounds.instantiate(self.tcx(), impl_substs);
let normalized_bounds =
project::normalize_with_depth(self, cause.clone(), recursion_depth, &bounds);
let normalized_bounds =
self.infcx().plug_leaks(skol_map, snapshot, &normalized_bounds);
let mut impl_obligations =
let predicates = ty::lookup_predicates(self.tcx(), def_id);
let predicates = predicates.instantiate(self.tcx(), substs);
let predicates = normalize_with_depth(self, cause.clone(), recursion_depth, &predicates);
let predicates = self.infcx().plug_leaks(skol_map, snapshot, &predicates);
let mut obligations =
util::predicates_for_generics(self.tcx(),
cause,
recursion_depth,
&normalized_bounds.value);
impl_obligations.extend(TypeSpace, normalized_bounds.obligations.into_iter());
impl_obligations
&predicates.value);
obligations.extend(TypeSpace, predicates.obligations.into_iter());
obligations
}
#[allow(unused_comparisons)]
@ -2307,8 +2564,10 @@ impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> {
PhantomFnCandidate => format!("PhantomFnCandidate"),
ErrorCandidate => format!("ErrorCandidate"),
BuiltinCandidate(b) => format!("BuiltinCandidate({:?})", b),
BuiltinObjectCandidate => format!("BuiltinObjectCandidate"),
ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)),
ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)),
DefaultImplCandidate(t) => format!("DefaultImplCandidate({:?})", t),
ProjectionCandidate => format!("ProjectionCandidate"),
FnPointerCandidate => format!("FnPointerCandidate"),
ObjectCandidate => {

@ -20,7 +20,7 @@ use util::nodemap::FnvHashSet;
use util::ppaux::Repr;
use super::{Obligation, ObligationCause, PredicateObligation,
VtableImpl, VtableParam, VtableImplData};
VtableImpl, VtableParam, VtableImplData, VtableDefaultImplData};
struct PredicateSet<'a,'tcx:'a> {
tcx: &'a ty::ctxt<'tcx>,
@ -323,6 +323,35 @@ pub fn trait_ref_for_builtin_bound<'tcx>(
}
}
pub fn predicate_for_trait_ref<'tcx>(
cause: ObligationCause<'tcx>,
trait_ref: Rc<ty::TraitRef<'tcx>>,
recursion_depth: uint)
-> Result<PredicateObligation<'tcx>, ErrorReported>
{
Ok(Obligation {
cause: cause,
recursion_depth: recursion_depth,
predicate: trait_ref.as_predicate(),
})
}
pub fn predicate_for_default_trait_impl<'tcx>(
tcx: &ty::ctxt<'tcx>,
cause: ObligationCause<'tcx>,
trait_def_id: ast::DefId,
recursion_depth: uint,
param_ty: Ty<'tcx>)
-> Result<PredicateObligation<'tcx>, ErrorReported>
{
let trait_ref = Rc::new(ty::TraitRef {
def_id: trait_def_id,
substs: tcx.mk_substs(Substs::empty().with_self_ty(param_ty))
});
predicate_for_trait_ref(cause, trait_ref, recursion_depth)
}
pub fn predicate_for_builtin_bound<'tcx>(
tcx: &ty::ctxt<'tcx>,
cause: ObligationCause<'tcx>,
@ -332,11 +361,7 @@ pub fn predicate_for_builtin_bound<'tcx>(
-> Result<PredicateObligation<'tcx>, ErrorReported>
{
let trait_ref = try!(trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty));
Ok(Obligation {
cause: cause,
recursion_depth: recursion_depth,
predicate: trait_ref.as_predicate(),
})
predicate_for_trait_ref(cause, trait_ref, recursion_depth)
}
/// Cast a trait reference into a reference to one of its super
@ -444,6 +469,9 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> {
super::VtableImpl(ref v) =>
v.repr(tcx),
super::VtableDefaultImpl(ref t) =>
t.repr(tcx),
super::VtableClosure(ref d, ref s) =>
format!("VtableClosure({},{})",
d.repr(tcx),
@ -483,6 +511,14 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableBuiltinData<N> {
}
}
impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableDefaultImplData<N> {
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
format!("VtableDefaultImplData(trait_def_id={}, nested={})",
self.trait_def_id.repr(tcx),
self.nested.repr(tcx))
}
}
impl<'tcx> Repr<'tcx> for super::VtableObjectData<'tcx> {
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
format!("VtableObject(object_ty={})",

@ -756,6 +756,9 @@ pub struct ctxt<'tcx> {
/// Maps a trait onto a list of impls of that trait.
pub trait_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
/// Maps a trait onto a list of *default* trait implementations
default_trait_impls: RefCell<DefIdMap<ast::DefId>>,
/// Maps a DefId of a type to a list of its inherent impls.
/// Contains implementations of methods that are inherent to a type.
/// Methods in these implementations don't need to be exported.
@ -2478,6 +2481,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
destructor_for_type: RefCell::new(DefIdMap()),
destructors: RefCell::new(DefIdSet()),
trait_impls: RefCell::new(DefIdMap()),
default_trait_impls: RefCell::new(DefIdMap()),
inherent_impls: RefCell::new(DefIdMap()),
impl_items: RefCell::new(DefIdMap()),
used_unsafe: RefCell::new(NodeSet()),
@ -5156,6 +5160,9 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
&None => None
}
}
ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
Some(ty::node_id_to_trait_ref(cx, ast_trait_ref.ref_id))
}
_ => None
}
}
@ -5977,6 +5984,32 @@ pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
|| Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id)))
}
pub fn trait_default_impl(tcx: &ctxt, trait_def_id: DefId) -> Option<ast::DefId> {
match tcx.default_trait_impls.borrow().get(&trait_def_id) {
Some(id) => Some(*id),
None => None
}
}
pub fn trait_has_default_impl(tcx: &ctxt, trait_def_id: DefId) -> bool {
match tcx.lang_items.to_builtin_kind(trait_def_id) {
Some(BoundSend) | Some(BoundSync) => true,
_ => tcx.default_trait_impls.borrow().contains_key(&trait_def_id)
}
}
/// Records a trait-to-implementation mapping.
pub fn record_default_trait_implementation(tcx: &ctxt,
trait_def_id: DefId,
impl_def_id: DefId) {
// We're using the latest implementation found as the reference one.
// Duplicated implementations are caught and reported in the coherence
// step.
tcx.default_trait_impls.borrow_mut().insert(trait_def_id, impl_def_id);
}
/// Records a trait-to-implementation mapping.
pub fn record_trait_implementation(tcx: &ctxt,
trait_def_id: DefId,
@ -6059,11 +6092,22 @@ pub fn populate_implementations_for_trait_if_necessary(
}
csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id,
|implementation_def_id| {
|implementation_def_id|{
let impl_items = csearch::get_impl_items(&tcx.sess.cstore, implementation_def_id);
// Record the trait->implementation mapping.
record_trait_implementation(tcx, trait_id, implementation_def_id);
if csearch::is_default_trait(&tcx.sess.cstore, implementation_def_id) {
record_default_trait_implementation(tcx, trait_id,
implementation_def_id);
tcx.populated_external_traits.borrow_mut().insert(trait_id);
// Nothing else to do for default trait implementations since
// they are not allowed to have type parameters, methods, or any
// other item that could be associated to a trait implementation.
return;
} else {
// Record the trait->implementation mapping.
record_trait_implementation(tcx, trait_id, implementation_def_id);
}
// For any methods that use a default implementation, add them to
// the map. This is a bit unfortunate.

@ -507,6 +507,15 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableImplData<
}
}
impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableDefaultImplData<N> {
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableDefaultImplData<N> {
traits::VtableDefaultImplData {
trait_def_id: self.trait_def_id,
nested: self.nested.fold_with(folder),
}
}
}
impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableBuiltinData<N> {
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableBuiltinData<N> {
traits::VtableBuiltinData {
@ -519,6 +528,7 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N>
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Vtable<'tcx, N> {
match *self {
traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)),
traits::VtableDefaultImpl(ref t) => traits::VtableDefaultImpl(t.fold_with(folder)),
traits::VtableClosure(d, ref s) => {
traits::VtableClosure(d, s.fold_with(folder))
}

@ -206,7 +206,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
ast::ItemEnum(..) | ast::ItemStruct(..) |
ast::ItemTrait(..) | ast::ItemImpl(..) |
ast::ItemMac(..) => {
ast::ItemMac(..) | ast::ItemDefaultImpl(..) => {
None
}

@ -209,7 +209,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
match item.node {
// impls/extern blocks do not break the "public chain" because they
// cannot have visibility qualifiers on them anyway
ast::ItemImpl(..) | ast::ItemForeignMod(..) => {}
ast::ItemImpl(..) | ast::ItemDefaultImpl(..) | ast::ItemForeignMod(..) => {}
// Traits are a little special in that even if they themselves are
// not public they may still be exported.
@ -802,7 +802,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
def::DefVariant(..) => ck("variant"),
def::DefTy(_, false) => ck("type"),
def::DefTy(_, true) => ck("enum"),
def::DefTrait(..) => ck("trait"),
def::DefaultImpl(..) => ck("trait"),
def::DefStruct(..) => ck("struct"),
def::DefMethod(_, Some(..), _) => ck("trait method"),
def::DefMethod(..) => ck("method"),
@ -1145,6 +1145,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
}
}
ast::ItemDefaultImpl(..) |
ast::ItemConst(..) | ast::ItemStatic(..) | ast::ItemStruct(..) |
ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) |
ast::ItemExternCrate(_) | ast::ItemUse(_) | ast::ItemMac(..) => {}
@ -1204,7 +1205,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
}
}
ast::ItemExternCrate(_) | ast::ItemUse(_) |
ast::ItemDefaultImpl(..) | ast::ItemExternCrate(_) | ast::ItemUse(_) |
ast::ItemStatic(..) | ast::ItemConst(..) |
ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) |
ast::ItemMac(..) => {}

@ -40,7 +40,7 @@ use syntax::ast::{Block, Crate};
use syntax::ast::{DeclItem, DefId};
use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic};
use syntax::ast::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};
use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl};
use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse};
use syntax::ast::{MethodImplItem, Name, NamedField, NodeId};
use syntax::ast::{PathListIdent, PathListMod};
@ -656,6 +656,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
parent.clone()
}
ItemDefaultImpl(_, _) |
ItemImpl(_, _, _, Some(_), _, _) => parent.clone(),
ItemTrait(_, _, _, ref items) => {
@ -735,7 +736,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
self.trait_item_map.insert((name, def_id), kind);
}
name_bindings.define_type(DefTrait(def_id), sp, modifiers);
name_bindings.define_type(DefaultImpl(def_id), sp, modifiers);
parent.clone()
}
ItemMac(..) => parent.clone()
@ -917,7 +918,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
}
child_name_bindings.define_value(def, DUMMY_SP, modifiers);
}
DefTrait(def_id) => {
DefaultImpl(def_id) => {
debug!("(building reduced graph for external \
crate) building type {}", final_ident);

@ -70,7 +70,7 @@ use syntax::ast::{ExprClosure, ExprLoop, ExprWhile, ExprMethodCall};
use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl};
use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics};
use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate};
use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};
use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl};
use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse};
use syntax::ast::{Local, MethodImplItem, Mod, Name, NodeId};
use syntax::ast::{Pat, PatEnum, PatIdent, PatLit};
@ -2840,6 +2840,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
});
}
ItemDefaultImpl(_, ref trait_ref) => {
self.resolve_trait_reference(item.id, trait_ref, TraitImplementation);
}
ItemImpl(_, _,
ref generics,
ref implemented_traits,
@ -2986,7 +2989,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// check for imports shadowing primitive types
if let ast::ViewPathSimple(ident, _) = view_path.node {
match self.def_map.borrow().get(&item.id) {
Some(&DefTy(..)) | Some(&DefStruct(..)) | Some(&DefTrait(..)) | None => {
Some(&DefTy(..)) | Some(&DefStruct(..)) | Some(&DefaultImpl(..)) | None => {
self.check_if_primitive_type_name(ident.name, item.span);
}
_ => {}
@ -3196,7 +3199,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
Some(def) => {
match def {
(DefTrait(_), _) => {
(DefaultImpl(_), _) => {
debug!("(resolving trait) found trait def: {:?}", def);
self.record_def(trait_reference.ref_id, def);
}
@ -4672,7 +4675,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
None => continue
};
let trait_def_id = match def {
DefTrait(trait_def_id) => trait_def_id,
DefaultImpl(trait_def_id) => trait_def_id,
_ => continue,
};
if self.trait_item_map.contains_key(&(name, trait_def_id)) {
@ -4688,7 +4691,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
Some(target) => target,
};
let did = match target.bindings.def_for_namespace(TypeNS) {
Some(DefTrait(trait_def_id)) => trait_def_id,
Some(DefaultImpl(trait_def_id)) => trait_def_id,
Some(..) | None => continue,
};
if self.trait_item_map.contains_key(&(name, did)) {

@ -239,7 +239,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
def::DefTy(..) |
def::DefAssociatedTy(..) |
def::DefAssociatedPath(..) |
def::DefTrait(_) => Some(recorder::TypeRef),
def::DefaultImpl(_) => Some(recorder::TypeRef),
def::DefStatic(_, _) |
def::DefConst(_) |
def::DefLocal(_) |

@ -207,7 +207,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
def::DefUpvar(..) => {
datum_callee(bcx, ref_expr)
}
def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) |
def::DefMod(..) | def::DefForeignMod(..) | def::DefaultImpl(..) |
def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) |
def::DefUse(..) | def::DefTyParamBinder(..) |
def::DefRegion(..) | def::DefLabel(..) | def::DefTyParam(..) |

@ -390,6 +390,7 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
Callee { bcx: bcx, data: Fn(llfn) }
}
traits::VtableBuiltin(..) |
traits::VtableDefaultImpl(..) |
traits::VtableParam(..) => {
bcx.sess().bug(
&format!("resolved vtable bad vtable {} in trans",
@ -714,6 +715,8 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let methods = traits::supertraits(tcx, trait_ref.clone()).flat_map(|trait_ref| {
let vtable = fulfill_obligation(ccx, DUMMY_SP, trait_ref.clone());
match vtable {
// Should default trait error here?
traits::VtableDefaultImpl(_) |
traits::VtableBuiltin(_) => {
Vec::new().into_iter()
}

@ -617,7 +617,7 @@ pub fn instantiate_trait_ref<'tcx>(
-> Rc<ty::TraitRef<'tcx>>
{
match ::lookup_def_tcx(this.tcx(), ast_trait_ref.path.span, ast_trait_ref.ref_id) {
def::DefTrait(trait_def_id) => {
def::DefaultImpl(trait_def_id) => {
let trait_ref = ast_path_to_trait_ref(this,
rscope,
trait_def_id,
@ -931,7 +931,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
match ty.node {
ast::TyPath(ref path, id) => {
match this.tcx().def_map.borrow().get(&id) {
Some(&def::DefTrait(trait_def_id)) => {
Some(&def::DefaultImpl(trait_def_id)) => {
let mut projection_bounds = Vec::new();
let trait_ref = object_path_to_poly_trait_ref(this,
rscope,
@ -1211,7 +1211,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
Some(&d) => d
};
match a_def {
def::DefTrait(trait_def_id) => {
def::DefaultImpl(trait_def_id) => {
// N.B. this case overlaps somewhat with
// TyObjectSum, see that fn for details
let mut projection_bounds = Vec::new();
@ -1821,7 +1821,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
match *ast_bound {
ast::TraitTyParamBound(ref b, ast::TraitBoundModifier::None) => {
match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
def::DefTrait(trait_did) => {
def::DefaultImpl(trait_did) => {
match trait_def_ids.get(&trait_did) {
// Already seen this trait. We forbid
// duplicates in the list (for some

@ -435,7 +435,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
let def = tcx.def_map.borrow()[pat.id].clone();
let (enum_def_id, variant_def_id) = match def {
def::DefTrait(_) => {
def::DefaultImpl(_) => {
let name = pprust::path_to_string(path);
span_err!(tcx.sess, pat.span, E0168,
"use of trait `{}` in a struct pattern", name);

@ -330,7 +330,7 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
cstore: &cstore::CStore,
dl: decoder::DefLike) {
match dl {
decoder::DlDef(def::DefTrait(did)) => {
decoder::DlDef(def::DefaultImpl(did)) => {
traits.push(TraitInfo::new(did));
}
decoder::DlDef(def::DefMod(did)) => {

@ -3862,7 +3862,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
variant_id, &fields[..]);
enum_id
}
Some(def::DefTrait(def_id)) => {
Some(def::DefaultImpl(def_id)) => {
span_err!(tcx.sess, path.span, E0159,
"use of trait `{}` as a struct constructor",
pprust::path_to_string(path));
@ -4634,7 +4634,7 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
def::DefStruct(id) | def::DefConst(id) => {
(ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id))
}
def::DefTrait(_) |
def::DefaultImpl(_) |
def::DefTy(..) |
def::DefAssociatedTy(..) |
def::DefAssociatedPath(..) |
@ -4738,7 +4738,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
def::DefTy(..) |
def::DefAssociatedTy(..) |
def::DefAssociatedPath(..) |
def::DefTrait(..) |
def::DefaultImpl(..) |
def::DefPrimTy(..) |
def::DefTyParam(..) => {
// Everything but the final segment should have no

@ -83,12 +83,15 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
}
ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(ref tref), _, _) => {
let trait_ref = ty::node_id_to_trait_ref(ccx.tcx, tref.ref_id);
ty::populate_implementations_for_trait_if_necessary(ccx.tcx, trait_ref.def_id);
match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
Some(ty::BoundSend) | Some(ty::BoundSync) => {}
Some(_) | None => {
span_err!(ccx.tcx.sess, item.span, E0192,
"negative impls are currently \
allowed just for `Send` and `Sync`")
if !ty::trait_has_default_impl(ccx.tcx, trait_ref.def_id) {
span_err!(ccx.tcx.sess, item.span, E0192,
"negative impls are only allowed for traits with \
default impls (e.g., `Send` and `Sync`)")
}
}
}
}

@ -96,6 +96,16 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
}
}
}
ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
// "Trait" impl
debug!("coherence2::orphan check: default trait impl {}", item.repr(self.tcx));
let trait_ref = ty::node_id_to_trait_ref(self.tcx, ast_trait_ref.ref_id);
if trait_ref.def_id.krate != ast::LOCAL_CRATE {
span_err!(self.tcx.sess, item.span, E0318,
"cannot create default implementations for traits outside the \
crate they're defined in; define a new trait instead.");
}
}
_ => {
// Not an impl
}

@ -17,16 +17,22 @@ use middle::infer::{self, new_infer_ctxt};
use syntax::ast::{DefId};
use syntax::ast::{LOCAL_CRATE};
use syntax::ast;
use syntax::codemap::{Span};
use syntax::ast_util;
use syntax::visit;
use syntax::codemap::Span;
use util::ppaux::Repr;
pub fn check(tcx: &ty::ctxt) {
let overlap = OverlapChecker { tcx: tcx };
let mut overlap = OverlapChecker { tcx: tcx };
overlap.check_for_overlapping_impls();
// this secondary walk specifically checks for impls of defaulted
// traits, for which additional overlap rules exist
visit::walk_crate(&mut overlap, tcx.map.krate());
}
struct OverlapChecker<'cx, 'tcx:'cx> {
tcx: &'cx ty::ctxt<'tcx>
tcx: &'cx ty::ctxt<'tcx>,
}
impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
@ -90,17 +96,28 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
return;
}
span_err!(self.tcx.sess, self.span_of_impl(impl1_def_id), E0119,
self.report_overlap_error(trait_def_id, impl1_def_id, impl2_def_id);
}
fn report_overlap_error(&self, trait_def_id: ast::DefId,
impl1: ast::DefId, impl2: ast::DefId) {
span_err!(self.tcx.sess, self.span_of_impl(impl1), E0119,
"conflicting implementations for trait `{}`",
ty::item_path_str(self.tcx, trait_def_id));
if impl2_def_id.krate == ast::LOCAL_CRATE {
span_note!(self.tcx.sess, self.span_of_impl(impl2_def_id),
self.report_overlap_note(impl1, impl2);
}
fn report_overlap_note(&self, impl1: ast::DefId, impl2: ast::DefId) {
if impl2.krate == ast::LOCAL_CRATE {
span_note!(self.tcx.sess, self.span_of_impl(impl2),
"note conflicting implementation here");
} else {
let crate_store = &self.tcx.sess.cstore;
let cdata = crate_store.get_crate_data(impl2_def_id.krate);
span_note!(self.tcx.sess, self.span_of_impl(impl1_def_id),
let cdata = crate_store.get_crate_data(impl2.krate);
span_note!(self.tcx.sess, self.span_of_impl(impl1),
"conflicting implementation in crate `{}`",
cdata.name);
}
@ -111,3 +128,33 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
self.tcx.map.span(impl_did.node)
}
}
impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
fn visit_item(&mut self, item: &'v ast::Item) {
match item.node {
ast::ItemDefaultImpl(_, _) => {
let impl_def_id = ast_util::local_def(item.id);
match ty::impl_trait_ref(self.tcx, impl_def_id) {
Some(ref trait_ref) => {
match ty::trait_default_impl(self.tcx, trait_ref.def_id) {
Some(other_impl) if other_impl != impl_def_id => {
self.report_overlap_error(trait_ref.def_id,
other_impl,
impl_def_id);
}
Some(_) => {}
None => {
self.tcx.sess.bug(
&format!("no default implementation recorded for `{:?}`",
item)[]);
}
}
}
_ => {}
}
}
_ => {}
}
}
}

@ -648,6 +648,12 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
predicates,
&enum_definition.variants);
},
ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
let trait_ref = astconv::instantiate_trait_ref(ccx, &ExplicitRscope,
ast_trait_ref, None, None);
ty::record_default_trait_implementation(tcx, trait_ref.def_id, local_def(it.id))
}
ast::ItemImpl(_, _,
ref generics,
ref opt_trait_ref,
@ -1141,6 +1147,7 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs));
ty::TypeScheme { ty: t, generics: ty_generics }
}
ast::ItemDefaultImpl(..) |
ast::ItemTrait(..) |
ast::ItemImpl(..) |
ast::ItemMod(..) |
@ -1183,6 +1190,7 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
ast::ItemStruct(_, ref generics) => {
ty_generic_bounds_for_type_or_impl(ccx, &scheme.generics, generics)
}
ast::ItemDefaultImpl(..) |
ast::ItemTrait(..) |
ast::ItemExternCrate(..) |
ast::ItemUse(..) |

@ -171,7 +171,9 @@ register_diagnostics! {
E0247, // found module name used as a type
E0248, // found value name used as a type
E0249, // expected constant expr for array length
E0250 // expected constant expr for array length
E0250, // expected constant expr for array length
E0318, // can't create default impls for traits outside their crates
E0319 // trait impls for defaulted traits allowed just for structs/enums
}
__build_diagnostic_array! { DIAGNOSTICS }

@ -476,6 +476,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> {
ast::ItemExternCrate(_) |
ast::ItemUse(_) |
ast::ItemDefaultImpl(..) |
ast::ItemImpl(..) |
ast::ItemStatic(..) |
ast::ItemConst(..) |
@ -626,6 +627,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
ast::ItemForeignMod(..) |
ast::ItemTy(..) |
ast::ItemImpl(..) |
ast::ItemDefaultImpl(..) |
ast::ItemMac(..) => {
}
}

@ -69,7 +69,7 @@ fn try_inline_def(cx: &DocContext, tcx: &ty::ctxt,
let mut ret = Vec::new();
let did = def.def_id();
let inner = match def {
def::DefTrait(did) => {
def::DefaultImpl(did) => {
record_extern_fqn(cx, did, clean::TypeTrait);
clean::TraitItem(build_external_trait(cx, tcx, did))
}

@ -2431,7 +2431,7 @@ fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId {
def::DefFn(i, _) => (i, TypeFunction),
def::DefTy(i, false) => (i, TypeTypedef),
def::DefTy(i, true) => (i, TypeEnum),
def::DefTrait(i) => (i, TypeTrait),
def::DefaultImpl(i) => (i, TypeTrait),
def::DefStruct(i) => (i, TypeStruct),
def::DefMod(i) => (i, TypeModule),
def::DefStatic(i, _) => (i, TypeStatic),

@ -39,6 +39,7 @@ pub struct Module {
pub vis: ast::Visibility,
pub stab: Option<attr::Stability>,
pub impls: Vec<Impl>,
pub def_traits: Vec<DefaultImpl>,
pub foreigns: Vec<ast::ForeignMod>,
pub macros: Vec<Macro>,
pub is_crate: bool,
@ -65,6 +66,7 @@ impl Module {
constants : Vec::new(),
traits : Vec::new(),
impls : Vec::new(),
def_traits : Vec::new(),
foreigns : Vec::new(),
macros : Vec::new(),
is_crate : false,
@ -196,6 +198,12 @@ pub struct Impl {
pub id: ast::NodeId,
}
pub struct DefaultImpl {
pub unsafety: ast::Unsafety,
pub trait_: ast::TraitRef,
pub id: ast::NodeId,
}
pub struct Macro {
pub name: Ident,
pub id: ast::NodeId,

@ -358,6 +358,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
};
om.impls.push(i);
},
ast::ItemDefaultImpl(unsafety, ref trait_ref) => {
let i = DefaultImpl {
unsafety: unsafety,
trait_: trait_ref.clone(),
id: item.id
};
om.def_traits.push(i);
}
ast::ItemForeignMod(ref fm) => {
om.foreigns.push(fm.clone());
}

@ -1641,6 +1641,10 @@ pub enum Item_ {
Generics,
TyParamBounds,
Vec<TraitItem>),
// Default trait implementations
// `impl Trait for ..`
ItemDefaultImpl(Unsafety, TraitRef),
ItemImpl(Unsafety,
ImplPolarity,
Generics,
@ -1666,7 +1670,8 @@ impl Item_ {
ItemStruct(..) => "struct",
ItemTrait(..) => "trait",
ItemMac(..) |
ItemImpl(..) => "item"
ItemImpl(..) |
ItemDefaultImpl(..) => "item"
}
}
}

@ -1044,6 +1044,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
ItemStruct(..) => "struct",
ItemTrait(..) => "trait",
ItemImpl(..) => "impl",
ItemDefaultImpl(..) => "default impl",
ItemMac(..) => "macro"
};
format!("{} {}{}", item_str, path_str, id_str)

@ -252,8 +252,12 @@ pub fn name_to_dummy_lifetime(name: Name) -> Lifetime {
/// hint of where they came from, (previously they would all just be
/// listed as `__extensions__::method_name::hash`, with no indication
/// of the type).
pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> Ident {
let mut pretty = pprust::ty_to_string(ty);
pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: Option<&Ty>) -> Ident {
let mut pretty = match ty {
Some(t) => pprust::ty_to_string(t),
None => String::from_str("..")
};
match *trait_ref {
Some(ref trait_ref) => {
pretty.push('.');

@ -498,7 +498,7 @@ impl<'a> TraitDef<'a> {
// Just mark it now since we know that it'll end up used downstream
attr::mark_used(&attr);
let opt_trait_ref = Some(trait_ref);
let ident = ast_util::impl_pretty_name(&opt_trait_ref, &*self_type);
let ident = ast_util::impl_pretty_name(&opt_trait_ref, Some(&*self_type));
let mut a = vec![attr];
a.extend(self.attributes.iter().cloned());
cx.item(

@ -999,6 +999,9 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
let struct_def = folder.fold_struct_def(struct_def);
ItemStruct(struct_def, folder.fold_generics(generics))
}
ItemDefaultImpl(unsafety, ref trait_ref) => {
ItemDefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
}
ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => {
let new_impl_items = impl_items.into_iter().flat_map(|item| {
folder.fold_impl_item(item).into_iter()
@ -1150,7 +1153,7 @@ pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span}
let ident = match node {
// The node may have changed, recompute the "pretty" impl name.
ItemImpl(_, _, _, ref maybe_trait, ref ty, _) => {
ast_util::impl_pretty_name(maybe_trait, &**ty)
ast_util::impl_pretty_name(maybe_trait, Some(&**ty))
}
_ => ident
};

@ -31,7 +31,7 @@ use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl};
use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy};
use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic};
use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst};
use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy};
use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy, ItemDefaultImpl};
use ast::{ItemExternCrate, ItemUse};
use ast::{LifetimeDef, Lit, Lit_};
use ast::{LitBool, LitChar, LitByte, LitBinary};
@ -4787,10 +4787,13 @@ impl<'a> Parser<'a> {
(impl_items, inner_attrs)
}
/// Parses two variants (with the region/type params always optional):
/// Parses items implementations variants
/// impl<T> Foo { ... }
/// impl<T> ToString for ~[T] { ... }
/// impl<T> ToString for &'static T { ... }
/// impl Send for .. {}
fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo {
let impl_span = self.span;
// First, parse type parameters if necessary.
let mut generics = self.parse_generics();
@ -4811,7 +4814,7 @@ impl<'a> Parser<'a> {
// Parse traits, if necessary.
let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
// New-style trait. Reinterpret the type as a trait.
let opt_trait_ref = match ty.node {
match ty.node {
TyPath(ref path, node_id) => {
Some(TraitRef {
path: (*path).clone(),
@ -4822,10 +4825,7 @@ impl<'a> Parser<'a> {
self.span_err(ty.span, "not a trait");
None
}
};
ty = self.parse_ty_sum();
opt_trait_ref
}
} else {
match polarity {
ast::ImplPolarity::Negative => {
@ -4838,14 +4838,27 @@ impl<'a> Parser<'a> {
None
};
self.parse_where_clause(&mut generics);
let (impl_items, attrs) = self.parse_impl_items();
if self.eat(&token::DotDot) {
if generics.is_parameterized() {
self.span_err(impl_span, "default trait implementations are not \
allowed to have genercis");
}
let ident = ast_util::impl_pretty_name(&opt_trait, &*ty);
self.expect(&token::OpenDelim(token::Brace));
self.expect(&token::CloseDelim(token::Brace));
(ast_util::impl_pretty_name(&opt_trait, None),
ItemDefaultImpl(unsafety, opt_trait.unwrap()), None)
} else {
if opt_trait.is_some() {
ty = self.parse_ty_sum();
}
self.parse_where_clause(&mut generics);
let (impl_items, attrs) = self.parse_impl_items();
(ident,
ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items),
Some(attrs))
(ast_util::impl_pretty_name(&opt_trait, Some(&*ty)),
ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items),
Some(attrs))
}
}
/// Parse a::B<String,i32>

@ -926,6 +926,18 @@ impl<'a> State<'a> {
try!(self.print_struct(&**struct_def, generics, item.ident, item.span));
}
ast::ItemDefaultImpl(unsafety, ref trait_ref) => {
try!(self.head(""));
try!(self.print_visibility(item.vis));
try!(self.print_unsafety(unsafety));
try!(self.word_nbsp("impl"));
try!(self.print_trait_ref(trait_ref));
try!(space(&mut self.s));
try!(self.word_space("for"));
try!(self.word_space(".."));
try!(self.bopen());
try!(self.bclose(item.span));
}
ast::ItemImpl(unsafety,
polarity,
ref generics,

@ -282,6 +282,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
visitor.visit_generics(type_parameters);
walk_enum_def(visitor, enum_definition, type_parameters)
}
ItemDefaultImpl(_, ref trait_ref) => {
visitor.visit_trait_ref(trait_ref)
}
ItemImpl(_, _,
ref type_parameters,
ref trait_reference,

@ -332,6 +332,7 @@ pub fn winsorize<T: Float + FromPrimitive>(samples: &mut [T], pct: T) {
/// Returns a HashMap with the number of occurrences of every element in the
/// sequence that the iterator exposes.
#[cfg(not(stage0))]
pub fn freq_count<T, U>(iter: T) -> hash_map::HashMap<U, uint>
where T: Iterator<Item=U>, U: Eq + Clone + Hash
{

@ -0,0 +1,24 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
#![feature(optin_builtin_traits)]
use std::marker::MarkerTrait;
trait MyTrait: MarkerTrait {}
impl MyTrait for .. {}
impl MyTrait for .. {}
//~^ ERROR conflicting implementations for trait `MyTrait`
fn main() {}

@ -34,6 +34,7 @@ unsafe impl Send for [MyType] {}
unsafe impl Send for &'static [NotSync] {}
//~^ ERROR builtin traits can only be implemented on structs or enums
//~^^ ERROR conflicting implementations for trait `core::marker::Send`
fn is_send<T: Send>() {}

@ -47,4 +47,7 @@ fn main() {
//~^^^^ ERROR overflow evaluating
//~^^^^^ NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate
//~^^^^^^ NOTE required by `is_send`
//~^^^^^^^ ERROR overflow evaluating
//~^^^^^^^^ NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate
//~^^^^^^^^^ NOTE required by `is_send`
}

@ -0,0 +1,18 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(optin_builtin_traits)]
trait MyDefaultImpl {}
impl<T> MyDefaultImpl for .. {}
//~^ ERROR default trait implementations are not allowed to have genercis
fn main() {}

@ -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 <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.
// Test that we do not consider associated types to be sendable without
// some applicable trait bound (and we don't ICE).
trait Trait {
type AssocType;
fn dummy(&self) { }
}
fn bar<T:Trait+Send>() {
is_send::<T::AssocType>(); //~ ERROR not implemented
}
fn is_send<T:Send>() {
}
fn main() { }

@ -0,0 +1,32 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(optin_builtin_traits)]
use std::marker::MarkerTrait;
trait MyTrait: MarkerTrait {}
impl MyTrait for .. {}
struct MyS;
struct MyS2;
impl !MyTrait for MyS2 {}
fn is_mytrait<T: MyTrait>() {}
fn main() {
is_mytrait::<MyS>();
is_mytrait::<(MyS2, MyS)>();
//~^ ERROR the trait `MyTrait` is not implemented for the type `MyS2`
}

@ -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 <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.
#![feature(optin_builtin_traits)]
use std::marker::MarkerTrait;
trait MyTrait: MarkerTrait {}
impl MyTrait for .. {}
impl<T> !MyTrait for *mut T {}
struct MyS;
struct MyS2;
impl !MyTrait for MyS2 {}
struct MyS3;
fn is_mytrait<T: MyTrait>() {}
fn main() {
is_mytrait::<MyS>();
is_mytrait::<MyS2>();
//~^ ERROR the trait `MyTrait` is not implemented for the type `MyS2`
}

@ -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 <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.
#![feature(optin_builtin_traits)]
struct MySendable {
t: *mut u8
}
unsafe impl Send for MySendable {}
struct MyNotSendable {
t: *mut u8
}
impl !Send for MyNotSendable {}
fn is_send<T: Send>() {}
fn main() {
is_send::<MySendable>();
is_send::<MyNotSendable>();
//~^ ERROR the trait `core::marker::Send` is not implemented for the type `MyNotSendable`
}

@ -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 <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.
// ignore-tidy-linelength
#![feature(optin_builtin_traits)]
use std::marker::Managed;
use std::cell::UnsafeCell;
struct MySync {
t: *mut u8
}
unsafe impl Sync for MySync {}
struct MyNotSync {
t: *mut u8
}
impl !Sync for MyNotSync {}
struct MyTypeWUnsafe {
t: UnsafeCell<u8>
}
struct MyTypeManaged {
t: Managed
}
fn is_sync<T: Sync>() {}
fn main() {
is_sync::<MySync>();
is_sync::<MyNotSync>();
//~^ ERROR the trait `core::marker::Sync` is not implemented for the type `MyNotSync`
is_sync::<MyTypeWUnsafe>();
//~^ ERROR the trait `core::marker::Sync` is not implemented for the type `core::cell::UnsafeCell<u8>`
is_sync::<MyTypeManaged>();
//~^ ERROR the trait `core::marker::Sync` is not implemented for the type `core::marker::Managed`
}

@ -0,0 +1,44 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(optin_builtin_traits)]
use std::marker::MarkerTrait;
trait MyTrait: MarkerTrait {}
impl MyTrait for .. {}
unsafe trait MyUnsafeTrait: MarkerTrait {}
unsafe impl MyUnsafeTrait for .. {}
struct ThisImplsTrait;
impl !MyUnsafeTrait for ThisImplsTrait {}
struct ThisImplsUnsafeTrait;
impl !MyTrait for ThisImplsUnsafeTrait {}
fn is_my_trait<T: MyTrait>() {}
fn is_my_unsafe_trait<T: MyUnsafeTrait>() {}
fn main() {
is_my_trait::<ThisImplsTrait>();
is_my_trait::<ThisImplsUnsafeTrait>();
//~^ ERROR the trait `MyTrait` is not implemented for the type `ThisImplsUnsafeTrait`
is_my_unsafe_trait::<ThisImplsTrait>();
//~^ ERROR the trait `MyUnsafeTrait` is not implemented for the type `ThisImplsTrait`
is_my_unsafe_trait::<ThisImplsUnsafeTrait>();
}

@ -0,0 +1,18 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
#![feature(optin_builtin_traits)]
impl Copy for .. {}
//~^ ERROR cannot create default implementations for traits outside the crate they're defined in; define a new trait instead.
fn main() {}

@ -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 <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.
// Test that declaring that `&T` is `Defaulted` if `T:Signed` implies
// that other `&T` is NOT `Defaulted` if `T:Signed` does not hold. In
// other words, the `..` impl only applies if there are no existing
// impls whose types unify.
#![feature(optin_builtin_traits)]
use std::marker::MarkerTrait;
trait Defaulted : MarkerTrait { }
impl Defaulted for .. { }
impl<'a,T:Signed> Defaulted for &'a T { }
impl<'a,T:Signed> Defaulted for &'a mut T { }
fn is_defaulted<T:Defaulted>() { }
trait Signed : MarkerTrait { }
impl Signed for i32 { }
fn main() {
is_defaulted::<&'static i32>();
is_defaulted::<&'static u32>();
//~^ ERROR the trait `Signed` is not implemented for the type `u32`
}

@ -0,0 +1,21 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test that we do not consider parameter types to be sendable without
// an explicit trait bound.
fn foo<T>() {
is_send::<T>() //~ ERROR not implemented
}
fn is_send<T:Send>() {
}
fn main() { }

@ -0,0 +1,29 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test that when a `..` impl applies, we also check that any
// supertrait conditions are met.
#![feature(optin_builtin_traits)]
use std::marker::MarkerTrait;
trait MyTrait : 'static {}
impl MyTrait for .. {}
fn foo<T:MyTrait>() { }
fn bar<'a>() {
foo::<&'a ()>(); //~ ERROR does not fulfill the required lifetime
}
fn main() {
}

@ -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 <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.
// Test that when a `..` impl applies, we also check that any
// supertrait conditions are met.
#![feature(optin_builtin_traits)]
use std::marker::MarkerTrait;
trait NotImplemented: MarkerTrait { }
trait MyTrait : NotImplemented {}
impl MyTrait for .. {}
fn foo<T:MyTrait>() { bar::<T>() }
fn bar<T:NotImplemented>() { }
fn main() {
foo::<i32>(); //~ ERROR the trait `NotImplemented` is not implemented for the type `i32`
bar::<i64>(); //~ ERROR the trait `NotImplemented` is not implemented for the type `i64`
}

@ -0,0 +1,47 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// Test that when a `..` impl applies, we also check that any
// supertrait conditions are met.
#![feature(optin_builtin_traits)]
use std::marker::MarkerTrait;
trait NotImplemented: MarkerTrait { }
trait MyTrait: MarkerTrait
where Option<Self> : NotImplemented
{}
impl NotImplemented for i32 {}
impl MyTrait for .. {}
fn foo<T:MyTrait>() {
bar::<Option<T>>()
//~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<T>`
//
// This should probably typecheck. This is #20671.
}
fn bar<T:NotImplemented>() { }
fn test() {
bar::<Option<i32>>();
//~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<i32>`
}
fn main() {
foo::<i32>();
//~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<i32>`
}

@ -17,6 +17,6 @@ trait TestTrait {
}
impl !TestTrait for TestType {}
//~^ ERROR negative impls are currently allowed just for `Send` and `Sync`
//~^ ERROR negative impls are only allowed for traits with default impls (e.g., `Send` and `Sync`)
fn main() {}

@ -8,4 +8,4 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
impl Foo; //~ ERROR expected one of `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;`
impl Foo; //~ ERROR expected one of `(`, `+`, `..`, `::`, `<`, `for`, `where`, or `{`, found `;`

@ -13,7 +13,7 @@ struct S {
}
impl Cmp, ToString for S {
//~^ ERROR: expected one of `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `,`
//~^ ERROR: expected one of `(`, `+`, `..`, `::`, `<`, `for`, `where`, or `{`, found `,`
fn eq(&&other: S) { false }
fn to_string(&self) -> String { "hi".to_string() }
}

@ -13,7 +13,9 @@ trait Foo {
struct Bar;
impl Foo + Owned for Bar { //~ ERROR not a trait
impl Foo + Owned for Bar {
//~^ ERROR not a trait
//~^^ ERROR expected one of `..`, `where`, or `{`, found `Bar`
}
fn main() { }

@ -0,0 +1,21 @@
// 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.
#![feature(optin_builtin_traits)]
// pp-exact
use std::marker::MarkerTrait;
trait MyTrait: MarkerTrait { }
impl MyTrait for .. { }
pub fn main() { }