look for default trait candidates
This commit is contained in:
parent
4148d5361a
commit
a962d47ef8
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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)),
|
||||
|
@ -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(
|
||||
|
@ -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 => {
|
||||
|
@ -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),
|
||||
|
@ -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.
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user