VtableParam(Vec<N>),
/// Virtual calls through an object
- VtableObject(VtableObjectData<'tcx>),
+ VtableObject(VtableObjectData<'tcx, N>),
/// Successful resolution for a builtin trait.
VtableBuiltin(VtableBuiltinData<N>),
VtableClosure(VtableClosureData<'tcx, N>),
/// Same as above, but for a fn pointer type with the given signature.
- VtableFnPointer(ty::Ty<'tcx>),
+ VtableFnPointer(VtableFnPointerData<'tcx, N>),
}
/// Identifies a particular impl in the source, along with a set of
/// A vtable for some object-safe trait `Foo` automatically derived
/// for the object type `Foo`.
#[derive(PartialEq,Eq,Clone)]
-pub struct VtableObjectData<'tcx> {
+pub struct VtableObjectData<'tcx, N> {
/// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`.
pub upcast_trait_ref: ty::PolyTraitRef<'tcx>,
/// The vtable is formed by concatenating together the method lists of
/// the base object trait and all supertraits; this is the start of
/// `upcast_trait_ref`'s methods in that vtable.
- pub vtable_base: usize
+ pub vtable_base: usize,
+
+ pub nested: Vec<N>,
+}
+
+#[derive(Clone, PartialEq, Eq)]
+pub struct VtableFnPointerData<'tcx, N> {
+ pub fn_ty: ty::Ty<'tcx>,
+ pub nested: Vec<N>
}
/// Creates predicate obligations from the generic bounds.
VtableBuiltin(i) => i.nested,
VtableDefaultImpl(d) => d.nested,
VtableClosure(c) => c.nested,
- VtableObject(_) | VtableFnPointer(..) => vec![]
+ VtableObject(d) => d.nested,
+ VtableFnPointer(d) => d.nested,
}
}
VtableImpl(i) => VtableImpl(VtableImplData {
impl_def_id: i.impl_def_id,
substs: i.substs,
- nested: i.nested.into_iter().map(f).collect()
+ nested: i.nested.into_iter().map(f).collect(),
}),
VtableParam(n) => VtableParam(n.into_iter().map(f).collect()),
VtableBuiltin(i) => VtableBuiltin(VtableBuiltinData {
- nested: i.nested.into_iter().map(f).collect()
+ nested: i.nested.into_iter().map(f).collect(),
+ }),
+ VtableObject(o) => VtableObject(VtableObjectData {
+ upcast_trait_ref: o.upcast_trait_ref,
+ vtable_base: o.vtable_base,
+ nested: o.nested.into_iter().map(f).collect(),
}),
- VtableObject(o) => VtableObject(o),
VtableDefaultImpl(d) => VtableDefaultImpl(VtableDefaultImplData {
trait_def_id: d.trait_def_id,
- nested: d.nested.into_iter().map(f).collect()
+ nested: d.nested.into_iter().map(f).collect(),
+ }),
+ VtableFnPointer(p) => VtableFnPointer(VtableFnPointerData {
+ fn_ty: p.fn_ty,
+ nested: p.nested.into_iter().map(f).collect(),
}),
- VtableFnPointer(f) => VtableFnPointer(f),
VtableClosure(c) => VtableClosure(VtableClosureData {
closure_def_id: c.closure_def_id,
substs: c.substs,
use super::SelectionContext;
use super::SelectionError;
use super::VtableClosureData;
+use super::VtableFnPointerData;
use super::VtableImplData;
use super::util;
Closure(VtableClosureData<'tcx, PredicateObligation<'tcx>>),
// fn pointer return type
- FnPointer(Ty<'tcx>),
+ FnPointer(VtableFnPointerData<'tcx, PredicateObligation<'tcx>>),
}
struct ProjectionTyCandidateSet<'tcx> {
candidate_set.vec.push(
ProjectionTyCandidate::Closure(data));
}
- super::VtableFnPointer(fn_type) => {
+ super::VtableFnPointer(data) => {
candidate_set.vec.push(
- ProjectionTyCandidate::FnPointer(fn_type));
+ ProjectionTyCandidate::FnPointer(data));
}
super::VtableParam(..) => {
// This case tell us nothing about the value of an
confirm_closure_candidate(selcx, obligation, closure_vtable)
}
- ProjectionTyCandidate::FnPointer(fn_type) => {
- confirm_fn_pointer_candidate(selcx, obligation, fn_type)
+ ProjectionTyCandidate::FnPointer(fn_pointer_vtable) => {
+ confirm_fn_pointer_candidate(selcx, obligation, fn_pointer_vtable)
}
}
}
fn confirm_fn_pointer_candidate<'cx, 'gcx, 'tcx>(
selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
obligation: &ProjectionTyObligation<'tcx>,
- fn_type: Ty<'tcx>)
+ fn_pointer_vtable: VtableFnPointerData<'tcx, PredicateObligation<'tcx>>)
-> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
{
- let fn_type = selcx.infcx().shallow_resolve(fn_type);
+ // FIXME(#32730) propagate obligations (fn pointer vtable nested obligations ONLY come from
+ // unification in inference)
+ assert!(fn_pointer_vtable.nested.is_empty());
+ let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty);
let sig = fn_type.fn_sig();
confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
}
use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
VtableFnPointer, VtableObject, VtableDefaultImpl};
use super::{VtableImplData, VtableObjectData, VtableBuiltinData,
- VtableClosureData, VtableDefaultImplData};
+ VtableClosureData, VtableDefaultImplData, VtableFnPointerData};
use super::util;
use hir::def_id::DefId;
use ty::fast_reject;
use ty::relate::TypeRelation;
+use rustc_data_structures::snapshot_vec::{SnapshotVecDelegate, SnapshotVec};
use std::cell::RefCell;
use std::fmt;
+use std::marker::PhantomData;
use std::rc::Rc;
use syntax::abi::Abi;
use hir;
use util::nodemap::FnvHashMap;
+struct InferredObligationsSnapshotVecDelegate<'tcx> {
+ phantom: PhantomData<&'tcx i32>,
+}
+impl<'tcx> SnapshotVecDelegate for InferredObligationsSnapshotVecDelegate<'tcx> {
+ type Value = PredicateObligation<'tcx>;
+ type Undo = ();
+ fn reverse(_: &mut Vec<Self::Value>, _: Self::Undo) {}
+}
+
pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
/// there is no type that the user could *actually name* that
/// would satisfy it. This avoids crippling inference, basically.
intercrate: bool,
+
+ inferred_obligations: SnapshotVec<InferredObligationsSnapshotVecDelegate<'tcx>>,
}
// A stack that walks back up the stack frame.
infcx: infcx,
freshener: infcx.freshener(),
intercrate: false,
+ inferred_obligations: SnapshotVec::new(),
}
}
infcx: infcx,
freshener: infcx.freshener(),
intercrate: true,
+ inferred_obligations: SnapshotVec::new(),
}
}
}
FnPointerCandidate => {
- let fn_type =
+ let data =
self.confirm_fn_pointer_candidate(obligation)?;
- Ok(VtableFnPointer(fn_type))
+ Ok(VtableFnPointer(data))
}
ProjectionCandidate => {
fn confirm_object_candidate(&mut self,
obligation: &TraitObligation<'tcx>)
- -> VtableObjectData<'tcx>
+ -> VtableObjectData<'tcx, PredicateObligation<'tcx>>
{
debug!("confirm_object_candidate({:?})",
obligation);
}
+ // FIXME(#32730) propagate obligations
VtableObjectData {
upcast_trait_ref: upcast_trait_ref.unwrap(),
vtable_base: vtable_base,
+ nested: vec![]
}
}
- fn confirm_fn_pointer_candidate(&mut self,
- obligation: &TraitObligation<'tcx>)
- -> Result<ty::Ty<'tcx>,SelectionError<'tcx>>
+ fn confirm_fn_pointer_candidate(&mut self, obligation: &TraitObligation<'tcx>)
+ -> Result<VtableFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>>
{
debug!("confirm_fn_pointer_candidate({:?})",
obligation);
self.confirm_poly_trait_refs(obligation.cause.clone(),
obligation.predicate.to_poly_trait_ref(),
trait_ref)?;
- Ok(self_ty)
+ // FIXME(#32730) propagate obligations
+ Ok(VtableFnPointerData { fn_ty: self_ty, nested: vec![] })
}
fn confirm_closure_candidate(&mut self,
}
}
-impl<'tcx> fmt::Debug for traits::VtableObjectData<'tcx> {
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableObjectData<'tcx, N> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "VtableObject(upcast={:?}, vtable_base={})",
+ write!(f, "VtableObject(upcast={:?}, vtable_base={}, nested={:?})",
self.upcast_trait_ref,
- self.vtable_base)
+ self.vtable_base,
+ self.nested)
+ }
+}
+
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableFnPointerData<'tcx, N> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "VtableFnPointer(fn_ty={:?}, nested={:?})",
+ self.fn_ty,
+ self.nested)
}
}
})
})
}
- traits::VtableFnPointer(ty) => {
- tcx.lift(&ty).map(traits::VtableFnPointer)
+ traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) => {
+ tcx.lift(&fn_ty).map(|fn_ty| {
+ traits::VtableFnPointer(traits::VtableFnPointerData {
+ fn_ty: fn_ty,
+ nested: nested,
+ })
+ })
}
traits::VtableParam(n) => Some(traits::VtableParam(n)),
traits::VtableBuiltin(d) => Some(traits::VtableBuiltin(d)),
traits::VtableObject(traits::VtableObjectData {
upcast_trait_ref,
- vtable_base
+ vtable_base,
+ nested
}) => {
tcx.lift(&upcast_trait_ref).map(|trait_ref| {
traits::VtableObject(traits::VtableObjectData {
upcast_trait_ref: trait_ref,
- vtable_base: vtable_base
+ vtable_base: vtable_base,
+ nested: nested
})
})
}
}
}
-impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> {
+impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx, N> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
traits::VtableObjectData {
upcast_trait_ref: self.upcast_trait_ref.fold_with(folder),
- vtable_base: self.vtable_base
+ vtable_base: self.vtable_base,
+ nested: self.nested.fold_with(folder),
+ }
+ }
+
+ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+ self.upcast_trait_ref.visit_with(visitor) || self.nested.visit_with(visitor)
+ }
+}
+
+impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableFnPointerData<'tcx, N> {
+ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+ traits::VtableFnPointerData {
+ fn_ty: self.fn_ty.fold_with(folder),
+ nested: self.nested.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
- self.upcast_trait_ref.visit_with(visitor)
+ self.fn_ty.visit_with(visitor) || self.nested.visit_with(visitor)
}
}
/// Given an upcast trait object described by `object`, returns the
/// index of the method `method_def_id` (which should be part of
/// `object.upcast_trait_ref`) within the vtable for `object`.
- pub fn get_vtable_index_of_object_method(self,
- object: &super::VtableObjectData<'tcx>,
- method_def_id: DefId) -> usize {
+ pub fn get_vtable_index_of_object_method<N>(self,
+ object: &super::VtableObjectData<'tcx, N>,
+ method_def_id: DefId) -> usize {
// Count number of methods preceding the one we are selecting and
// add them to the total offset.
// Skip over associated types and constants.
};
Callee::ptr(immediate_rvalue(llfn, fn_ptr_ty))
}
- traits::VtableFnPointer(fn_ty) => {
+ traits::VtableFnPointer(vtable_fn_pointer) => {
let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
- let llfn = trans_fn_pointer_shim(ccx, trait_closure_kind, fn_ty);
+ let llfn = trans_fn_pointer_shim(ccx, trait_closure_kind, vtable_fn_pointer.fn_ty);
let method_ty = def_ty(tcx, def_id, substs);
let fn_ptr_ty = match method_ty.sty {
trait_closure_kind);
vec![llfn].into_iter()
}
- traits::VtableFnPointer(bare_fn_ty) => {
+ traits::VtableFnPointer(
+ traits::VtableFnPointerData {
+ fn_ty: bare_fn_ty,
+ nested: _ }) => {
let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap();
vec![trans_fn_pointer_shim(ccx, trait_closure_kind, bare_fn_ty)].into_iter()
}