look for default trait candidates

This commit is contained in:
Flavio Percoco 2015-01-24 14:17:24 +01:00
parent 4148d5361a
commit a962d47ef8
10 changed files with 75 additions and 8 deletions

View File

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

View File

@ -1563,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::DefTrait => true,
_ => false
}
}

View File

@ -221,6 +221,9 @@ pub enum Vtable<'tcx, N> {
/// Vtable identifying a particular impl.
VtableImpl(VtableImplData<'tcx, N>),
/// Vtable for default trait implementations
VtableDefaultTrait(ast::DefId),
/// 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
@ -513,17 +516,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(_) |
VtableDefaultTrait(..) | 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)),
VtableDefaultTrait(t) => VtableDefaultTrait(t),
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 +543,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),
VtableDefaultTrait(t) => VtableDefaultTrait(t),
VtableParam(n) => VtableParam(n.into_iter().map(op).collect()),
VtableObject(p) => VtableObject(p),
VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)),

View File

@ -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::VtableDefaultTrait(..) |
super::VtableBuiltin(..) => {
// These traits have no associated types.
selcx.tcx().sess.span_bug(

View File

@ -26,7 +26,7 @@ use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch
use super::{Selection};
use super::{SelectionResult};
use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
VtableFnPointer, VtableObject};
VtableFnPointer, VtableObject, VtableDefaultTrait};
use super::{VtableImplData, VtableObjectData, VtableBuiltinData};
use super::object_safety;
use super::{util};
@ -136,6 +136,7 @@ enum SelectionCandidate<'tcx> {
BuiltinCandidate(ty::BuiltinBound),
ParamCandidate(ty::PolyTraitRef<'tcx>),
ImplCandidate(ast::DefId),
DefaultTraitCandidate(ast::DefId),
/// This is a trait matching with a projected type as `Self`, and
/// we found an applicable bound in the trait definition.
@ -1130,7 +1131,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) =
@ -1144,6 +1146,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
});
}
if self.tcx().default_trait_impls.borrow().contains(&def_id) {
candidates.vec.push(DefaultTraitCandidate(def_id.clone()))
}
Ok(())
}
@ -1646,6 +1653,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(VtableParam(obligations))
}
DefaultTraitCandidate(trait_def_id) => {
Ok(VtableDefaultTrait(trait_def_id))
}
ImplCandidate(impl_def_id) => {
let vtable_impl =
try!(self.confirm_impl_candidate(obligation, impl_def_id));
@ -2308,6 +2319,7 @@ impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> {
BuiltinCandidate(b) => format!("BuiltinCandidate({:?})", b),
ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)),
ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)),
DefaultTraitCandidate(t) => format!("DefaultTraitCandidate({:?})", t),
ProjectionCandidate => format!("ProjectionCandidate"),
FnPointerCandidate => format!("FnPointerCandidate"),
ObjectCandidate => {

View File

@ -444,6 +444,9 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> {
super::VtableImpl(ref v) =>
v.repr(tcx),
super::VtableDefaultTrait(ref t) =>
format!("VtableDefaultTrait({:?})", t),
super::VtableClosure(ref d, ref s) =>
format!("VtableClosure({},{})",
d.repr(tcx),

View File

@ -757,6 +757,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
pub default_trait_impls: RefCell<DefIdSet>,
/// 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.
@ -2493,6 +2496,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(DefIdSet()),
inherent_impls: RefCell::new(DefIdMap()),
impl_items: RefCell::new(DefIdMap()),
used_unsafe: RefCell::new(NodeSet()),
@ -5992,6 +5996,18 @@ pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
|| Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id)))
}
/// Records a trait-to-implementation mapping.
pub fn record_default_trait_implementation(tcx: &ctxt, trait_def_id: DefId) {
//assert!(did.krate != ast::LOCAL_CRATE);
if tcx.default_trait_impls.borrow().contains(&trait_def_id) {
return;
}
tcx.default_trait_impls.borrow_mut().insert(trait_def_id);
}
/// Records a trait-to-implementation mapping.
pub fn record_trait_implementation(tcx: &ctxt,
trait_def_id: DefId,
@ -6074,11 +6090,21 @@ 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);
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.

View File

@ -519,6 +519,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::VtableDefaultTrait(t) => traits::VtableDefaultTrait(t),
traits::VtableClosure(d, ref s) => {
traits::VtableClosure(d, s.fold_with(folder))
}

View File

@ -390,6 +390,7 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
Callee { bcx: bcx, data: Fn(llfn) }
}
traits::VtableBuiltin(..) |
traits::VtableDefaultTrait(..) |
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::VtableDefaultTrait(_) |
traits::VtableBuiltin(_) => {
Vec::new().into_iter()
}

View File

@ -649,7 +649,10 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
&enum_definition.variants);
},
ast::ItemDefTrait(_, 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)
}
ast::ItemImpl(_, _,
ref generics,