mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-23 05:55:25 +00:00
Auto merge of #44896 - qmx:move-resolve-to-librustc, r=arielb1
Move monomorphize::resolve() to librustc this moves `monomorphize::resolve(..)` to librustc, and re-enables inlining for some trait methods, fixing #44389 @nikomatsakis I've kept the calls to the new `ty::Instance::resolve(....)` always `.unwrap()`-ing for the moment, how/do you want to add more debugging info via `.unwrap_or()` or something like this? we still have some related `resolve_*` functions on monomorphize, but I wasn't sure moving them was into the scope for this PR too. @eddyb mind to take a look too?
This commit is contained in:
commit
8891044e89
@ -10,6 +10,10 @@
|
||||
|
||||
use hir::def_id::DefId;
|
||||
use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
|
||||
use ty::subst::{Kind, Subst};
|
||||
use traits;
|
||||
use syntax::abi::Abi;
|
||||
use syntax::codemap::DUMMY_SP;
|
||||
use util::ppaux;
|
||||
|
||||
use std::fmt;
|
||||
@ -111,4 +115,211 @@ impl<'a, 'b, 'tcx> Instance<'tcx> {
|
||||
pub fn def_id(&self) -> DefId {
|
||||
self.def.def_id()
|
||||
}
|
||||
|
||||
/// Resolve a (def_id, substs) pair to an (optional) instance -- most commonly,
|
||||
/// this is used to find the precise code that will run for a trait method invocation,
|
||||
/// if known.
|
||||
///
|
||||
/// Returns `None` if we cannot resolve `Instance` to a specific instance.
|
||||
/// For example, in a context like this,
|
||||
///
|
||||
/// ```
|
||||
/// fn foo<T: Debug>(t: T) { ... }
|
||||
/// ```
|
||||
///
|
||||
/// trying to resolve `Debug::fmt` applied to `T` will yield `None`, because we do not
|
||||
/// know what code ought to run. (Note that this setting is also affected by the
|
||||
/// `RevealMode` in the parameter environment.)
|
||||
///
|
||||
/// Presuming that coherence and type-check have succeeded, if this method is invoked
|
||||
/// in a monomorphic context (i.e., like during trans), then it is guaranteed to return
|
||||
/// `Some`.
|
||||
pub fn resolve(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
def_id: DefId,
|
||||
substs: &'tcx Substs<'tcx>) -> Option<Instance<'tcx>> {
|
||||
debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
|
||||
let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
|
||||
debug!(" => associated item, attempting to find impl");
|
||||
let item = tcx.associated_item(def_id);
|
||||
resolve_associated_item(tcx, &item, param_env, trait_def_id, substs)
|
||||
} else {
|
||||
let ty = tcx.type_of(def_id);
|
||||
let item_type = tcx.trans_apply_param_substs(substs, &ty);
|
||||
|
||||
let def = match item_type.sty {
|
||||
ty::TyFnDef(..) if {
|
||||
let f = item_type.fn_sig(tcx);
|
||||
f.abi() == Abi::RustIntrinsic ||
|
||||
f.abi() == Abi::PlatformIntrinsic
|
||||
} =>
|
||||
{
|
||||
debug!(" => intrinsic");
|
||||
ty::InstanceDef::Intrinsic(def_id)
|
||||
}
|
||||
_ => {
|
||||
if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
|
||||
let ty = substs.type_at(0);
|
||||
if ty.needs_drop(tcx, ty::ParamEnv::empty(traits::Reveal::All)) {
|
||||
debug!(" => nontrivial drop glue");
|
||||
ty::InstanceDef::DropGlue(def_id, Some(ty))
|
||||
} else {
|
||||
debug!(" => trivial drop glue");
|
||||
ty::InstanceDef::DropGlue(def_id, None)
|
||||
}
|
||||
} else {
|
||||
debug!(" => free item");
|
||||
ty::InstanceDef::Item(def_id)
|
||||
}
|
||||
}
|
||||
};
|
||||
Some(Instance {
|
||||
def: def,
|
||||
substs: substs
|
||||
})
|
||||
};
|
||||
debug!("resolve(def_id={:?}, substs={:?}) = {:?}", def_id, substs, result);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_closure<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
substs: ty::ClosureSubsts<'tcx>,
|
||||
requested_kind: ty::ClosureKind)
|
||||
-> Instance<'tcx>
|
||||
{
|
||||
let actual_kind = tcx.closure_kind(def_id);
|
||||
|
||||
match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
|
||||
Ok(true) => fn_once_adapter_instance(tcx, def_id, substs),
|
||||
_ => Instance::new(def_id, substs.substs)
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_associated_item<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
trait_item: &ty::AssociatedItem,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
trait_id: DefId,
|
||||
rcvr_substs: &'tcx Substs<'tcx>
|
||||
) -> Option<Instance<'tcx>> {
|
||||
let def_id = trait_item.def_id;
|
||||
debug!("resolve_associated_item(trait_item={:?}, \
|
||||
trait_id={:?}, \
|
||||
rcvr_substs={:?})",
|
||||
def_id, trait_id, rcvr_substs);
|
||||
|
||||
let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
|
||||
let vtbl = tcx.trans_fulfill_obligation(DUMMY_SP, param_env, ty::Binder(trait_ref));
|
||||
|
||||
// Now that we know which impl is being used, we can dispatch to
|
||||
// the actual function:
|
||||
match vtbl {
|
||||
traits::VtableImpl(impl_data) => {
|
||||
let (def_id, substs) = traits::find_associated_item(
|
||||
tcx, trait_item, rcvr_substs, &impl_data);
|
||||
let substs = tcx.erase_regions(&substs);
|
||||
Some(ty::Instance::new(def_id, substs))
|
||||
}
|
||||
traits::VtableGenerator(closure_data) => {
|
||||
Some(Instance {
|
||||
def: ty::InstanceDef::Item(closure_data.closure_def_id),
|
||||
substs: closure_data.substs.substs
|
||||
})
|
||||
}
|
||||
traits::VtableClosure(closure_data) => {
|
||||
let trait_closure_kind = tcx.lang_items().fn_trait_kind(trait_id).unwrap();
|
||||
Some(resolve_closure(tcx, closure_data.closure_def_id, closure_data.substs,
|
||||
trait_closure_kind))
|
||||
}
|
||||
traits::VtableFnPointer(ref data) => {
|
||||
Some(Instance {
|
||||
def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
|
||||
substs: rcvr_substs
|
||||
})
|
||||
}
|
||||
traits::VtableObject(ref data) => {
|
||||
let index = tcx.get_vtable_index_of_object_method(data, def_id);
|
||||
Some(Instance {
|
||||
def: ty::InstanceDef::Virtual(def_id, index),
|
||||
substs: rcvr_substs
|
||||
})
|
||||
}
|
||||
traits::VtableBuiltin(..) => {
|
||||
if let Some(_) = tcx.lang_items().clone_trait() {
|
||||
Some(Instance {
|
||||
def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()),
|
||||
substs: rcvr_substs
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
traits::VtableDefaultImpl(..) | traits::VtableParam(..) => None
|
||||
}
|
||||
}
|
||||
|
||||
fn needs_fn_once_adapter_shim<'a, 'tcx>(actual_closure_kind: ty::ClosureKind,
|
||||
trait_closure_kind: ty::ClosureKind)
|
||||
-> Result<bool, ()>
|
||||
{
|
||||
match (actual_closure_kind, trait_closure_kind) {
|
||||
(ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
|
||||
(ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
|
||||
(ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => {
|
||||
// No adapter needed.
|
||||
Ok(false)
|
||||
}
|
||||
(ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
|
||||
// The closure fn `llfn` is a `fn(&self, ...)`. We want a
|
||||
// `fn(&mut self, ...)`. In fact, at trans time, these are
|
||||
// basically the same thing, so we can just return llfn.
|
||||
Ok(false)
|
||||
}
|
||||
(ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
|
||||
(ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
|
||||
// The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
|
||||
// self, ...)`. We want a `fn(self, ...)`. We can produce
|
||||
// this by doing something like:
|
||||
//
|
||||
// fn call_once(self, ...) { call_mut(&self, ...) }
|
||||
// fn call_once(mut self, ...) { call_mut(&mut self, ...) }
|
||||
//
|
||||
// These are both the same at trans time.
|
||||
Ok(true)
|
||||
}
|
||||
(ty::ClosureKind::FnMut, _) |
|
||||
(ty::ClosureKind::FnOnce, _) => Err(())
|
||||
}
|
||||
}
|
||||
|
||||
fn fn_once_adapter_instance<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
closure_did: DefId,
|
||||
substs: ty::ClosureSubsts<'tcx>,
|
||||
) -> Instance<'tcx> {
|
||||
debug!("fn_once_adapter_shim({:?}, {:?})",
|
||||
closure_did,
|
||||
substs);
|
||||
let fn_once = tcx.lang_items().fn_once_trait().unwrap();
|
||||
let call_once = tcx.associated_items(fn_once)
|
||||
.find(|it| it.kind == ty::AssociatedKind::Method)
|
||||
.unwrap().def_id;
|
||||
let def = ty::InstanceDef::ClosureOnceShim { call_once };
|
||||
|
||||
let self_ty = tcx.mk_closure_from_closure_substs(
|
||||
closure_did, substs);
|
||||
|
||||
let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs);
|
||||
let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
|
||||
assert_eq!(sig.inputs().len(), 1);
|
||||
let substs = tcx.mk_substs([
|
||||
Kind::from(self_ty),
|
||||
Kind::from(sig.inputs()[0]),
|
||||
].iter().cloned());
|
||||
|
||||
debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
|
||||
Instance { def, substs }
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::visit::*;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::{self, Ty, TyCtxt, Instance};
|
||||
use rustc::ty::subst::{Subst,Substs};
|
||||
|
||||
use std::collections::VecDeque;
|
||||
@ -78,7 +78,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
||||
let mut callsites = VecDeque::new();
|
||||
|
||||
// Only do inlining into fn bodies.
|
||||
if let MirSource::Fn(_) = self.source {
|
||||
if let MirSource::Fn(caller_id) = self.source {
|
||||
for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated() {
|
||||
// Don't inline calls that are in cleanup blocks.
|
||||
if bb_data.is_cleanup { continue; }
|
||||
@ -87,17 +87,23 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
||||
let terminator = bb_data.terminator();
|
||||
if let TerminatorKind::Call {
|
||||
func: Operand::Constant(ref f), .. } = terminator.kind {
|
||||
if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty {
|
||||
if self.tcx.trait_of_item(callee_def_id).is_none() {
|
||||
callsites.push_back(CallSite {
|
||||
callee: callee_def_id,
|
||||
substs,
|
||||
bb,
|
||||
location: terminator.source_info
|
||||
});
|
||||
if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty {
|
||||
let caller_def_id = self.tcx.hir.local_def_id(caller_id);
|
||||
let param_env = self.tcx.param_env(caller_def_id);
|
||||
|
||||
if let Some(instance) = Instance::resolve(self.tcx,
|
||||
param_env,
|
||||
callee_def_id,
|
||||
substs) {
|
||||
callsites.push_back(CallSite {
|
||||
callee: instance.def_id(),
|
||||
substs: instance.substs,
|
||||
bb,
|
||||
location: terminator.source_info
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,9 +19,10 @@ use common::{self, CrateContext};
|
||||
use consts;
|
||||
use declare;
|
||||
use llvm::{self, ValueRef};
|
||||
use monomorphize::{self, Instance};
|
||||
use monomorphize::Instance;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::TypeFoldable;
|
||||
use rustc::ty::{self, TypeFoldable};
|
||||
use rustc::traits;
|
||||
use rustc::ty::subst::Substs;
|
||||
use type_of;
|
||||
|
||||
@ -179,5 +180,13 @@ pub fn resolve_and_get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
substs: &'tcx Substs<'tcx>)
|
||||
-> ValueRef
|
||||
{
|
||||
get_fn(ccx, monomorphize::resolve(ccx.tcx(), def_id, substs))
|
||||
get_fn(
|
||||
ccx,
|
||||
ty::Instance::resolve(
|
||||
ccx.tcx(),
|
||||
ty::ParamEnv::empty(traits::Reveal::All),
|
||||
def_id,
|
||||
substs
|
||||
).unwrap()
|
||||
)
|
||||
}
|
||||
|
@ -566,7 +566,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||
if let ConstVal::Unevaluated(def_id, substs) = constant.val {
|
||||
let substs = self.tcx.trans_apply_param_substs(self.param_substs,
|
||||
&substs);
|
||||
let instance = monomorphize::resolve(self.tcx, def_id, substs);
|
||||
let instance = ty::Instance::resolve(self.tcx,
|
||||
ty::ParamEnv::empty(traits::Reveal::All),
|
||||
def_id,
|
||||
substs).unwrap();
|
||||
collect_neighbours(self.tcx, instance, true, self.output);
|
||||
}
|
||||
|
||||
@ -587,7 +590,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||
|
||||
let constness = match (self.const_context, &callee_ty.sty) {
|
||||
(true, &ty::TyFnDef(def_id, substs)) if self.tcx.is_const_fn(def_id) => {
|
||||
let instance = monomorphize::resolve(self.tcx, def_id, substs);
|
||||
let instance =
|
||||
ty::Instance::resolve(self.tcx,
|
||||
ty::ParamEnv::empty(traits::Reveal::All),
|
||||
def_id,
|
||||
substs).unwrap();
|
||||
Some(instance)
|
||||
}
|
||||
_ => None
|
||||
@ -657,7 +664,10 @@ fn visit_fn_use<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
output: &mut Vec<TransItem<'tcx>>)
|
||||
{
|
||||
if let ty::TyFnDef(def_id, substs) = ty.sty {
|
||||
let instance = monomorphize::resolve(tcx, def_id, substs);
|
||||
let instance = ty::Instance::resolve(tcx,
|
||||
ty::ParamEnv::empty(traits::Reveal::All),
|
||||
def_id,
|
||||
substs).unwrap();
|
||||
visit_instance_use(tcx, instance, is_direct_call, output);
|
||||
}
|
||||
}
|
||||
@ -845,7 +855,11 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
// Walk all methods of the trait, including those of its supertraits
|
||||
let methods = traits::get_vtable_methods(tcx, poly_trait_ref);
|
||||
let methods = methods.filter_map(|method| method)
|
||||
.map(|(def_id, substs)| monomorphize::resolve(tcx, def_id, substs))
|
||||
.map(|(def_id, substs)| ty::Instance::resolve(
|
||||
tcx,
|
||||
ty::ParamEnv::empty(traits::Reveal::All),
|
||||
def_id,
|
||||
substs).unwrap())
|
||||
.filter(|&instance| should_trans_locally(tcx, &instance))
|
||||
.map(|instance| create_fn_trans_item(instance));
|
||||
output.extend(methods);
|
||||
@ -1000,8 +1014,10 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
continue;
|
||||
}
|
||||
|
||||
let instance =
|
||||
monomorphize::resolve(tcx, method.def_id, callee_substs);
|
||||
let instance = ty::Instance::resolve(tcx,
|
||||
ty::ParamEnv::empty(traits::Reveal::All),
|
||||
method.def_id,
|
||||
callee_substs).unwrap();
|
||||
|
||||
let trans_item = create_fn_trans_item(instance);
|
||||
if trans_item.is_instantiable(tcx) && should_trans_locally(tcx, &instance) {
|
||||
|
@ -13,6 +13,7 @@ use rustc::middle::lang_items;
|
||||
use rustc::middle::const_val::{ConstEvalErr, ConstInt, ErrKind};
|
||||
use rustc::ty::{self, Ty, TypeFoldable};
|
||||
use rustc::ty::layout::{self, LayoutTyper};
|
||||
use rustc::traits;
|
||||
use rustc::mir;
|
||||
use abi::{Abi, FnType, ArgType};
|
||||
use adt;
|
||||
@ -429,7 +430,10 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||
|
||||
let (instance, mut llfn) = match callee.ty.sty {
|
||||
ty::TyFnDef(def_id, substs) => {
|
||||
(Some(monomorphize::resolve(bcx.ccx.tcx(), def_id, substs)),
|
||||
(Some(ty::Instance::resolve(bcx.ccx.tcx(),
|
||||
ty::ParamEnv::empty(traits::Reveal::All),
|
||||
def_id,
|
||||
substs).unwrap()),
|
||||
None)
|
||||
}
|
||||
ty::TyFnPtr(_) => {
|
||||
|
@ -14,6 +14,7 @@ use rustc_const_math::ConstInt::*;
|
||||
use rustc_const_math::{ConstInt, ConstMathErr};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::infer::TransNormalize;
|
||||
use rustc::traits;
|
||||
use rustc::mir;
|
||||
use rustc::mir::tcx::LvalueTy;
|
||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
@ -30,7 +31,6 @@ use common::{C_array, C_bool, C_bytes, C_int, C_uint, C_big_integral, C_u32, C_u
|
||||
use common::{C_null, C_struct, C_str_slice, C_undef, C_usize, C_vector, is_undef};
|
||||
use common::const_to_opt_u128;
|
||||
use consts;
|
||||
use monomorphize;
|
||||
use type_of;
|
||||
use type_::Type;
|
||||
use value::Value;
|
||||
@ -261,7 +261,10 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
substs: &'tcx Substs<'tcx>,
|
||||
args: IndexVec<mir::Local, Result<Const<'tcx>, ConstEvalErr<'tcx>>>)
|
||||
-> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
|
||||
let instance = monomorphize::resolve(ccx.tcx(), def_id, substs);
|
||||
let instance = ty::Instance::resolve(ccx.tcx(),
|
||||
ty::ParamEnv::empty(traits::Reveal::All),
|
||||
def_id,
|
||||
substs).unwrap();
|
||||
let mir = ccx.tcx().instance_mir(instance.def);
|
||||
MirConstContext::new(ccx, &mir, instance.substs, args).trans()
|
||||
}
|
||||
|
@ -8,9 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use abi::Abi;
|
||||
use common::*;
|
||||
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::middle::lang_items::DropInPlaceFnLangItem;
|
||||
use rustc::traits;
|
||||
@ -99,115 +96,6 @@ pub fn resolve_closure<'a, 'tcx> (
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_associated_item<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
trait_item: &ty::AssociatedItem,
|
||||
trait_id: DefId,
|
||||
rcvr_substs: &'tcx Substs<'tcx>
|
||||
) -> Instance<'tcx> {
|
||||
let def_id = trait_item.def_id;
|
||||
debug!("resolve_associated_item(trait_item={:?}, \
|
||||
trait_id={:?}, \
|
||||
rcvr_substs={:?})",
|
||||
def_id, trait_id, rcvr_substs);
|
||||
|
||||
let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
|
||||
let vtbl = tcx.trans_fulfill_obligation(
|
||||
DUMMY_SP, ty::ParamEnv::empty(traits::Reveal::All), ty::Binder(trait_ref));
|
||||
|
||||
// Now that we know which impl is being used, we can dispatch to
|
||||
// the actual function:
|
||||
match vtbl {
|
||||
traits::VtableImpl(impl_data) => {
|
||||
let (def_id, substs) = traits::find_associated_item(
|
||||
tcx, trait_item, rcvr_substs, &impl_data);
|
||||
let substs = tcx.erase_regions(&substs);
|
||||
ty::Instance::new(def_id, substs)
|
||||
}
|
||||
traits::VtableGenerator(closure_data) => {
|
||||
Instance {
|
||||
def: ty::InstanceDef::Item(closure_data.closure_def_id),
|
||||
substs: closure_data.substs.substs
|
||||
}
|
||||
}
|
||||
traits::VtableClosure(closure_data) => {
|
||||
let trait_closure_kind = tcx.lang_items().fn_trait_kind(trait_id).unwrap();
|
||||
resolve_closure(tcx, closure_data.closure_def_id, closure_data.substs,
|
||||
trait_closure_kind)
|
||||
}
|
||||
traits::VtableFnPointer(ref data) => {
|
||||
Instance {
|
||||
def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
|
||||
substs: rcvr_substs
|
||||
}
|
||||
}
|
||||
traits::VtableObject(ref data) => {
|
||||
let index = tcx.get_vtable_index_of_object_method(data, def_id);
|
||||
Instance {
|
||||
def: ty::InstanceDef::Virtual(def_id, index),
|
||||
substs: rcvr_substs
|
||||
}
|
||||
}
|
||||
traits::VtableBuiltin(..) if Some(trait_id) == tcx.lang_items().clone_trait() => {
|
||||
Instance {
|
||||
def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()),
|
||||
substs: rcvr_substs
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
bug!("static call to invalid vtable: {:?}", vtbl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The point where linking happens. Resolve a (def_id, substs)
|
||||
/// pair to an instance.
|
||||
pub fn resolve<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
substs: &'tcx Substs<'tcx>
|
||||
) -> Instance<'tcx> {
|
||||
debug!("resolve(def_id={:?}, substs={:?})",
|
||||
def_id, substs);
|
||||
let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
|
||||
debug!(" => associated item, attempting to find impl");
|
||||
let item = tcx.associated_item(def_id);
|
||||
resolve_associated_item(tcx, &item, trait_def_id, substs)
|
||||
} else {
|
||||
let item_type = def_ty(tcx, def_id, substs);
|
||||
let def = match item_type.sty {
|
||||
ty::TyFnDef(..) if {
|
||||
let f = item_type.fn_sig(tcx);
|
||||
f.abi() == Abi::RustIntrinsic ||
|
||||
f.abi() == Abi::PlatformIntrinsic
|
||||
} =>
|
||||
{
|
||||
debug!(" => intrinsic");
|
||||
ty::InstanceDef::Intrinsic(def_id)
|
||||
}
|
||||
_ => {
|
||||
if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
|
||||
let ty = substs.type_at(0);
|
||||
if type_needs_drop(tcx, ty) {
|
||||
debug!(" => nontrivial drop glue");
|
||||
ty::InstanceDef::DropGlue(def_id, Some(ty))
|
||||
} else {
|
||||
debug!(" => trivial drop glue");
|
||||
ty::InstanceDef::DropGlue(def_id, None)
|
||||
}
|
||||
} else {
|
||||
debug!(" => free item");
|
||||
ty::InstanceDef::Item(def_id)
|
||||
}
|
||||
}
|
||||
};
|
||||
Instance { def, substs }
|
||||
};
|
||||
debug!("resolve(def_id={:?}, substs={:?}) = {}",
|
||||
def_id, substs, result);
|
||||
result
|
||||
}
|
||||
|
||||
pub fn resolve_drop_in_place<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
ty: Ty<'tcx>)
|
||||
@ -215,7 +103,7 @@ pub fn resolve_drop_in_place<'a, 'tcx>(
|
||||
{
|
||||
let def_id = tcx.require_lang_item(DropInPlaceFnLangItem);
|
||||
let substs = tcx.intern_substs(&[Kind::from(ty)]);
|
||||
resolve(tcx, def_id, substs)
|
||||
Instance::resolve(tcx, ty::ParamEnv::empty(traits::Reveal::All), def_id, substs).unwrap()
|
||||
}
|
||||
|
||||
pub fn custom_coerce_unsize_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
Loading…
Reference in New Issue
Block a user