Ensure default trait impls hold
This commit is contained in:
parent
58a8103df9
commit
4b09209efe
5 changed files with 239 additions and 20 deletions
|
@ -222,7 +222,7 @@ pub enum Vtable<'tcx, N> {
|
||||||
VtableImpl(VtableImplData<'tcx, N>),
|
VtableImpl(VtableImplData<'tcx, N>),
|
||||||
|
|
||||||
/// Vtable for default trait implementations
|
/// Vtable for default trait implementations
|
||||||
VtableDefaultTrait(ast::DefId),
|
VtableDefaultTrait(VtableDefaultTraitData<N>),
|
||||||
|
|
||||||
/// Successful resolution to an obligation provided by the caller
|
/// Successful resolution to an obligation provided by the caller
|
||||||
/// for some type parameter. The `Vec<N>` represents the
|
/// for some type parameter. The `Vec<N>` represents the
|
||||||
|
@ -262,6 +262,12 @@ pub struct VtableImplData<'tcx, N> {
|
||||||
pub nested: subst::VecPerParamSpace<N>
|
pub nested: subst::VecPerParamSpace<N>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug,Clone)]
|
||||||
|
pub struct VtableDefaultTraitData<N> {
|
||||||
|
pub trait_def_id: ast::DefId,
|
||||||
|
pub nested: subst::VecPerParamSpace<N>
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug,Clone)]
|
#[derive(Debug,Clone)]
|
||||||
pub struct VtableBuiltinData<N> {
|
pub struct VtableBuiltinData<N> {
|
||||||
pub nested: subst::VecPerParamSpace<N>
|
pub nested: subst::VecPerParamSpace<N>
|
||||||
|
@ -527,7 +533,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
|
||||||
pub fn map_nested<M, F>(&self, op: F) -> Vtable<'tcx, M> where F: FnMut(&N) -> M {
|
pub fn map_nested<M, F>(&self, op: F) -> Vtable<'tcx, M> where F: FnMut(&N) -> M {
|
||||||
match *self {
|
match *self {
|
||||||
VtableImpl(ref i) => VtableImpl(i.map_nested(op)),
|
VtableImpl(ref i) => VtableImpl(i.map_nested(op)),
|
||||||
VtableDefaultTrait(t) => VtableDefaultTrait(t),
|
VtableDefaultTrait(ref t) => VtableDefaultTrait(t.map_nested(op)),
|
||||||
VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()),
|
VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()),
|
||||||
VtableClosure(d, ref s) => VtableClosure(d, s.clone()),
|
VtableClosure(d, ref s) => VtableClosure(d, s.clone()),
|
||||||
VtableParam(ref n) => VtableParam(n.iter().map(op).collect()),
|
VtableParam(ref n) => VtableParam(n.iter().map(op).collect()),
|
||||||
|
@ -543,7 +549,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
|
||||||
VtableImpl(i) => VtableImpl(i.map_move_nested(op)),
|
VtableImpl(i) => VtableImpl(i.map_move_nested(op)),
|
||||||
VtableFnPointer(sig) => VtableFnPointer(sig),
|
VtableFnPointer(sig) => VtableFnPointer(sig),
|
||||||
VtableClosure(d, s) => VtableClosure(d, s),
|
VtableClosure(d, s) => VtableClosure(d, s),
|
||||||
VtableDefaultTrait(t) => VtableDefaultTrait(t),
|
VtableDefaultTrait(t) => VtableDefaultTrait(t.map_move_nested(op)),
|
||||||
VtableParam(n) => VtableParam(n.into_iter().map(op).collect()),
|
VtableParam(n) => VtableParam(n.into_iter().map(op).collect()),
|
||||||
VtableObject(p) => VtableObject(p),
|
VtableObject(p) => VtableObject(p),
|
||||||
VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)),
|
VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)),
|
||||||
|
@ -578,6 +584,31 @@ impl<'tcx, N> VtableImplData<'tcx, N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<N> VtableDefaultTraitData<N> {
|
||||||
|
pub fn iter_nested(&self) -> Iter<N> {
|
||||||
|
self.nested.iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn map_nested<M, F>(&self, op: F) -> VtableDefaultTraitData<M> where
|
||||||
|
F: FnMut(&N) -> M,
|
||||||
|
{
|
||||||
|
VtableDefaultTraitData {
|
||||||
|
trait_def_id: self.trait_def_id,
|
||||||
|
nested: self.nested.map(op)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn map_move_nested<M, F>(self, op: F) -> VtableDefaultTraitData<M> where
|
||||||
|
F: FnMut(N) -> M,
|
||||||
|
{
|
||||||
|
let VtableDefaultTraitData { trait_def_id, nested } = self;
|
||||||
|
VtableDefaultTraitData {
|
||||||
|
trait_def_id: trait_def_id,
|
||||||
|
nested: nested.map_move(op)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<N> VtableBuiltinData<N> {
|
impl<N> VtableBuiltinData<N> {
|
||||||
pub fn iter_nested(&self) -> Iter<N> {
|
pub fn iter_nested(&self) -> Iter<N> {
|
||||||
self.nested.iter()
|
self.nested.iter()
|
||||||
|
|
|
@ -21,13 +21,13 @@ use super::{DerivedObligationCause};
|
||||||
use super::{project};
|
use super::{project};
|
||||||
use super::project::Normalized;
|
use super::project::Normalized;
|
||||||
use super::{PredicateObligation, TraitObligation, ObligationCause};
|
use super::{PredicateObligation, TraitObligation, ObligationCause};
|
||||||
use super::{ObligationCauseCode, BuiltinDerivedObligation};
|
use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation};
|
||||||
use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
|
use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
|
||||||
use super::{Selection};
|
use super::{Selection};
|
||||||
use super::{SelectionResult};
|
use super::{SelectionResult};
|
||||||
use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
|
use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
|
||||||
VtableFnPointer, VtableObject, VtableDefaultTrait};
|
VtableFnPointer, VtableObject, VtableDefaultTrait};
|
||||||
use super::{VtableImplData, VtableObjectData, VtableBuiltinData};
|
use super::{VtableImplData, VtableObjectData, VtableBuiltinData, VtableDefaultTraitData};
|
||||||
use super::object_safety;
|
use super::object_safety;
|
||||||
use super::{util};
|
use super::{util};
|
||||||
|
|
||||||
|
@ -1535,7 +1535,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
ty::struct_fields(self.tcx(), def_id, substs).iter()
|
ty::struct_fields(self.tcx(), def_id, substs).iter()
|
||||||
.map(|f| f.mt.ty)
|
.map(|f| f.mt.ty)
|
||||||
.collect();
|
.collect();
|
||||||
nominal(self, bound, def_id, types)
|
nominal(bound, types)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_enum(def_id, substs) => {
|
ty::ty_enum(def_id, substs) => {
|
||||||
|
@ -1545,7 +1545,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
.flat_map(|variant| variant.args.iter())
|
.flat_map(|variant| variant.args.iter())
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
nominal(self, bound, def_id, types)
|
nominal(bound, types)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_projection(_) |
|
ty::ty_projection(_) |
|
||||||
|
@ -1594,9 +1594,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn nominal<'cx, 'tcx>(this: &mut SelectionContext<'cx, 'tcx>,
|
fn nominal<'cx, 'tcx>(bound: ty::BuiltinBound,
|
||||||
bound: ty::BuiltinBound,
|
|
||||||
def_id: ast::DefId,
|
|
||||||
types: Vec<Ty<'tcx>>)
|
types: Vec<Ty<'tcx>>)
|
||||||
-> Result<BuiltinBoundConditions<'tcx>,SelectionError<'tcx>>
|
-> Result<BuiltinBoundConditions<'tcx>,SelectionError<'tcx>>
|
||||||
{
|
{
|
||||||
|
@ -1615,6 +1613,89 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn constituent_types(&self, t: Ty<'tcx>) -> 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_char => {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
ty::ty_projection(..) |
|
||||||
|
ty::ty_param(..) |
|
||||||
|
ty::ty_infer(..) => {
|
||||||
|
self.tcx().sess.bug(
|
||||||
|
&format!(
|
||||||
|
"asked to assemble constituent types of unexpected type: {}",
|
||||||
|
t.repr(self.tcx()))[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ty::ty_uniq(referent_ty) => { // Box<T>
|
||||||
|
vec![referent_ty]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ty::ty_trait(ref data) => {
|
||||||
|
// Recursively check all supertraits to find out if any further
|
||||||
|
// bounds are required and thus we must fulfill.
|
||||||
|
let principal =
|
||||||
|
data.principal_trait_ref_with_self_ty(self.tcx(),
|
||||||
|
self.tcx().types.err);
|
||||||
|
|
||||||
|
|
||||||
|
util::supertraits(self.tcx(), principal).map(|tr| tr.self_ty()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
ty::ty_open(element_ty) => {vec![element_ty]},
|
||||||
|
|
||||||
|
ty::ty_ptr(ty::mt { ty: element_ty, ..}) |
|
||||||
|
ty::ty_rptr(_, ty::mt { ty: element_ty, ..}) => {
|
||||||
|
vec![element_ty]
|
||||||
|
},
|
||||||
|
|
||||||
|
ty::ty_vec(element_ty, _) => {
|
||||||
|
vec![element_ty]
|
||||||
|
}
|
||||||
|
|
||||||
|
ty::ty_tup(ref tys) => {
|
||||||
|
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
|
||||||
|
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) => {
|
||||||
|
upvars.iter().map(|c| c.ty).collect()
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ty::ty_struct(def_id, substs) => {
|
||||||
|
ty::struct_fields(self.tcx(), def_id, substs).iter()
|
||||||
|
.map(|f| f.mt.ty)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
ty::ty_enum(def_id, substs) => {
|
||||||
|
ty::substd_enum_variants(self.tcx(), def_id, substs)
|
||||||
|
.iter()
|
||||||
|
.flat_map(|variant| variant.args.iter())
|
||||||
|
.map(|&ty| ty)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// CONFIRMATION
|
// CONFIRMATION
|
||||||
//
|
//
|
||||||
|
@ -1648,7 +1729,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultTraitCandidate(trait_def_id) => {
|
DefaultTraitCandidate(trait_def_id) => {
|
||||||
Ok(VtableDefaultTrait(trait_def_id))
|
let data = try!(self.confirm_default_impl_candidate(obligation, trait_def_id));
|
||||||
|
Ok(VtableDefaultTrait(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
ImplCandidate(impl_def_id) => {
|
ImplCandidate(impl_def_id) => {
|
||||||
|
@ -1783,6 +1865,68 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
VtableBuiltinData { nested: obligations }
|
VtableBuiltinData { nested: obligations }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn confirm_default_impl_candidate(&mut self,
|
||||||
|
obligation: &TraitObligation<'tcx>,
|
||||||
|
impl_def_id: ast::DefId)
|
||||||
|
-> Result<VtableDefaultTraitData<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());
|
||||||
|
let types = self.constituent_types(self_ty);
|
||||||
|
Ok(self.vtable_default_impl(obligation, impl_def_id, types))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vtable_default_impl(&mut self,
|
||||||
|
obligation: &TraitObligation<'tcx>,
|
||||||
|
trait_def_id: ast::DefId,
|
||||||
|
nested: Vec<Ty<'tcx>>)
|
||||||
|
-> VtableDefaultTraitData<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 obligations = match obligations {
|
||||||
|
Ok(o) => o,
|
||||||
|
Err(ErrorReported) => Vec::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new());
|
||||||
|
debug!("vtable_default_impl_data: obligations={}", obligations.repr(self.tcx()));
|
||||||
|
|
||||||
|
VtableDefaultTraitData {
|
||||||
|
trait_def_id: trait_def_id,
|
||||||
|
nested: obligations
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn confirm_impl_candidate(&mut self,
|
fn confirm_impl_candidate(&mut self,
|
||||||
obligation: &TraitObligation<'tcx>,
|
obligation: &TraitObligation<'tcx>,
|
||||||
impl_def_id: ast::DefId)
|
impl_def_id: ast::DefId)
|
||||||
|
|
|
@ -20,7 +20,7 @@ use util::nodemap::FnvHashSet;
|
||||||
use util::ppaux::Repr;
|
use util::ppaux::Repr;
|
||||||
|
|
||||||
use super::{Obligation, ObligationCause, PredicateObligation,
|
use super::{Obligation, ObligationCause, PredicateObligation,
|
||||||
VtableImpl, VtableParam, VtableImplData};
|
VtableImpl, VtableParam, VtableImplData, VtableDefaultTraitData};
|
||||||
|
|
||||||
struct PredicateSet<'a,'tcx:'a> {
|
struct PredicateSet<'a,'tcx:'a> {
|
||||||
tcx: &'a ty::ctxt<'tcx>,
|
tcx: &'a ty::ctxt<'tcx>,
|
||||||
|
@ -323,6 +323,35 @@ pub fn trait_ref_for_builtin_bound<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn predicate_for_trait_ref<'tcx>(
|
||||||
|
tcx: &ty::ctxt<'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(tcx, cause, trait_ref, recursion_depth)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn predicate_for_builtin_bound<'tcx>(
|
pub fn predicate_for_builtin_bound<'tcx>(
|
||||||
tcx: &ty::ctxt<'tcx>,
|
tcx: &ty::ctxt<'tcx>,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
|
@ -332,11 +361,7 @@ pub fn predicate_for_builtin_bound<'tcx>(
|
||||||
-> Result<PredicateObligation<'tcx>, ErrorReported>
|
-> Result<PredicateObligation<'tcx>, ErrorReported>
|
||||||
{
|
{
|
||||||
let trait_ref = try!(trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty));
|
let trait_ref = try!(trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty));
|
||||||
Ok(Obligation {
|
predicate_for_trait_ref(tcx, cause, trait_ref, recursion_depth)
|
||||||
cause: cause,
|
|
||||||
recursion_depth: recursion_depth,
|
|
||||||
predicate: trait_ref.as_predicate(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cast a trait reference into a reference to one of its super
|
/// Cast a trait reference into a reference to one of its super
|
||||||
|
@ -445,7 +470,7 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> {
|
||||||
v.repr(tcx),
|
v.repr(tcx),
|
||||||
|
|
||||||
super::VtableDefaultTrait(ref t) =>
|
super::VtableDefaultTrait(ref t) =>
|
||||||
format!("VtableDefaultTrait({:?})", t),
|
t.repr(tcx),
|
||||||
|
|
||||||
super::VtableClosure(ref d, ref s) =>
|
super::VtableClosure(ref d, ref s) =>
|
||||||
format!("VtableClosure({},{})",
|
format!("VtableClosure({},{})",
|
||||||
|
@ -486,6 +511,14 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableBuiltinData<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableDefaultTraitData<N> {
|
||||||
|
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
||||||
|
format!("VtableDefaultTraitData(trait_def_id={}, nested={})",
|
||||||
|
self.trait_def_id.repr(tcx),
|
||||||
|
self.nested.repr(tcx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Repr<'tcx> for super::VtableObjectData<'tcx> {
|
impl<'tcx> Repr<'tcx> for super::VtableObjectData<'tcx> {
|
||||||
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
||||||
format!("VtableObject(object_ty={})",
|
format!("VtableObject(object_ty={})",
|
||||||
|
|
|
@ -5175,6 +5175,9 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
|
||||||
&None => None
|
&None => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast::ItemDefTrait(_, ref ast_trait_ref) => {
|
||||||
|
Some(ty::node_id_to_trait_ref(cx, ast_trait_ref.ref_id))
|
||||||
|
}
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5999,7 +6002,6 @@ pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
|
||||||
/// Records a trait-to-implementation mapping.
|
/// Records a trait-to-implementation mapping.
|
||||||
pub fn record_default_trait_implementation(tcx: &ctxt, trait_def_id: DefId) {
|
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) {
|
if tcx.default_trait_impls.borrow().contains(&trait_def_id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -507,6 +507,15 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableImplData<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableDefaultTraitData<N> {
|
||||||
|
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableDefaultTraitData<N> {
|
||||||
|
traits::VtableDefaultTraitData {
|
||||||
|
trait_def_id: self.trait_def_id,
|
||||||
|
nested: self.nested.fold_with(folder),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableBuiltinData<N> {
|
impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableBuiltinData<N> {
|
||||||
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableBuiltinData<N> {
|
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableBuiltinData<N> {
|
||||||
traits::VtableBuiltinData {
|
traits::VtableBuiltinData {
|
||||||
|
@ -519,7 +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> {
|
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Vtable<'tcx, N> {
|
||||||
match *self {
|
match *self {
|
||||||
traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)),
|
traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)),
|
||||||
traits::VtableDefaultTrait(t) => traits::VtableDefaultTrait(t),
|
traits::VtableDefaultTrait(ref t) => traits::VtableDefaultTrait(t.fold_with(folder)),
|
||||||
traits::VtableClosure(d, ref s) => {
|
traits::VtableClosure(d, ref s) => {
|
||||||
traits::VtableClosure(d, s.fold_with(folder))
|
traits::VtableClosure(d, s.fold_with(folder))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue