mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Auto merge of #35761 - nikomatsakis:faster-trans-fulfill-obligation, r=eddyb
Cache projections in trans This introduces a cache for the results of projection and normalization in trans. This is in addition to the existing cache that is per-inference-context. Trans is an easy place to put the cache because we are guaranteed not to have type parameters and also we don't expect any failures or inference variables, so there is no need to cache or follow-up on obligations that come along with. (As evidenced by the fact that this particular code would panic if any error occurred.) That said, I am not sure this is 100% the best place for it; I sort of wanted a cache like we have in the fulfillment context for global names; but that cache only triggers when all subsequent obligations are satisfied, and since projections don't have an entry in the obligation jungle there is no easy place to put it. I considered caching both the result and obligations globally, but haven't really tried implementing it. It might be a good next step. Regardless, this cache seems to have no real effect on bootstrap time (maybe a slight improvement), but on [the futures.rs test case I was looking at](https://github.com/rust-lang-nursery/rustc-benchmarks/pull/6), it improves performance quite a bit: | phase | before | after | | ----- | ------ | ----- | | collection | 0.79s | 0.46s | | translation | 6.8s | 3.2s | | total | 11.92s | 7.15s | r? @arielb1
This commit is contained in:
commit
497d67d708
@ -132,7 +132,7 @@ pub enum DepNode<D: Clone + Debug> {
|
||||
// which would yield an overly conservative dep-graph.
|
||||
TraitItems(D),
|
||||
ReprHints(D),
|
||||
TraitSelect(D, Vec<D>),
|
||||
TraitSelect(Vec<D>),
|
||||
}
|
||||
|
||||
impl<D: Clone + Debug> DepNode<D> {
|
||||
@ -237,10 +237,9 @@ impl<D: Clone + Debug> DepNode<D> {
|
||||
TraitImpls(ref d) => op(d).map(TraitImpls),
|
||||
TraitItems(ref d) => op(d).map(TraitItems),
|
||||
ReprHints(ref d) => op(d).map(ReprHints),
|
||||
TraitSelect(ref d, ref type_ds) => {
|
||||
let d = try_opt!(op(d));
|
||||
TraitSelect(ref type_ds) => {
|
||||
let type_ds = try_opt!(type_ds.iter().map(|d| op(d)).collect());
|
||||
Some(TraitSelect(d, type_ds))
|
||||
Some(TraitSelect(type_ds))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -136,13 +136,6 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
// avoid reporting the same error twice.
|
||||
pub reported_trait_errors: RefCell<FnvHashSet<traits::TraitErrorKey<'tcx>>>,
|
||||
|
||||
// This is a temporary field used for toggling on normalization in the inference context,
|
||||
// as we move towards the approach described here:
|
||||
// https://internals.rust-lang.org/t/flattening-the-contexts-for-fun-and-profit/2293
|
||||
// At a point sometime in the future normalization will be done by the typing context
|
||||
// directly.
|
||||
normalize: bool,
|
||||
|
||||
// Sadly, the behavior of projection varies a bit depending on the
|
||||
// stage of compilation. The specifics are given in the
|
||||
// documentation for `Reveal`.
|
||||
@ -458,7 +451,6 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
tables: Option<RefCell<ty::Tables<'tcx>>>,
|
||||
param_env: Option<ty::ParameterEnvironment<'gcx>>,
|
||||
projection_mode: Reveal,
|
||||
normalize: bool
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
|
||||
@ -473,19 +465,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
|
||||
tables: tables.map(RefCell::new),
|
||||
param_env: param_env,
|
||||
projection_mode: projection_mode,
|
||||
normalize: false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn normalizing_infer_ctxt(self, projection_mode: Reveal)
|
||||
-> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||
InferCtxtBuilder {
|
||||
global_tcx: self,
|
||||
arenas: ty::CtxtArenas::new(),
|
||||
tables: None,
|
||||
param_env: None,
|
||||
projection_mode: projection_mode,
|
||||
normalize: false
|
||||
}
|
||||
}
|
||||
|
||||
@ -506,7 +485,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
|
||||
evaluation_cache: traits::EvaluationCache::new(),
|
||||
projection_cache: RefCell::new(traits::ProjectionCache::new()),
|
||||
reported_trait_errors: RefCell::new(FnvHashSet()),
|
||||
normalize: false,
|
||||
projection_mode: Reveal::NotSpecializable,
|
||||
tainted_by_errors_flag: Cell::new(false),
|
||||
err_count_on_creation: self.sess.err_count(),
|
||||
@ -525,7 +503,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||
ref tables,
|
||||
ref mut param_env,
|
||||
projection_mode,
|
||||
normalize
|
||||
} = *self;
|
||||
let tables = if let Some(ref tables) = *tables {
|
||||
InferTables::Local(tables)
|
||||
@ -547,7 +524,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||
selection_cache: traits::SelectionCache::new(),
|
||||
evaluation_cache: traits::EvaluationCache::new(),
|
||||
reported_trait_errors: RefCell::new(FnvHashSet()),
|
||||
normalize: normalize,
|
||||
projection_mode: projection_mode,
|
||||
tainted_by_errors_flag: Cell::new(false),
|
||||
err_count_on_creation: tcx.sess.err_count(),
|
||||
@ -683,6 +659,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
self.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result)
|
||||
}
|
||||
|
||||
/// Finishes processes any obligations that remain in the
|
||||
/// fulfillment context, and then returns the result with all type
|
||||
/// variables removed and regions erased. Because this is intended
|
||||
/// for use after type-check has completed, if any errors occur,
|
||||
/// it will panic. It is used during normalization and other cases
|
||||
/// where processing the obligations in `fulfill_cx` may cause
|
||||
/// type inference variables that appear in `result` to be
|
||||
/// unified, and hence we need to process those obligations to get
|
||||
/// the complete picture of the type.
|
||||
pub fn drain_fulfillment_cx_or_panic<T>(&self,
|
||||
span: Span,
|
||||
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
|
||||
@ -692,45 +677,26 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
{
|
||||
debug!("drain_fulfillment_cx_or_panic()");
|
||||
|
||||
let when = "resolving bounds after type-checking";
|
||||
let v = match self.drain_fulfillment_cx(fulfill_cx, result) {
|
||||
Ok(v) => v,
|
||||
Err(errors) => {
|
||||
span_bug!(span, "Encountered errors `{:?}` {}", errors, when);
|
||||
}
|
||||
};
|
||||
|
||||
match self.tcx.lift_to_global(&v) {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
span_bug!(span, "Uninferred types/regions in `{:?}` {}", v, when);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Finishes processes any obligations that remain in the fulfillment
|
||||
/// context, and then "freshens" and returns `result`. This is
|
||||
/// primarily used during normalization and other cases where
|
||||
/// processing the obligations in `fulfill_cx` may cause type
|
||||
/// inference variables that appear in `result` to be unified, and
|
||||
/// hence we need to process those obligations to get the complete
|
||||
/// picture of the type.
|
||||
pub fn drain_fulfillment_cx<T>(&self,
|
||||
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
|
||||
result: &T)
|
||||
-> Result<T,Vec<traits::FulfillmentError<'tcx>>>
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
debug!("drain_fulfillment_cx(result={:?})",
|
||||
result);
|
||||
|
||||
// In principle, we only need to do this so long as `result`
|
||||
// contains unbound type parameters. It could be a slight
|
||||
// optimization to stop iterating early.
|
||||
fulfill_cx.select_all_or_error(self)?;
|
||||
match fulfill_cx.select_all_or_error(self) {
|
||||
Ok(()) => { }
|
||||
Err(errors) => {
|
||||
span_bug!(span, "Encountered errors `{:?}` resolving bounds after type-checking",
|
||||
errors);
|
||||
}
|
||||
}
|
||||
|
||||
let result = self.resolve_type_vars_if_possible(result);
|
||||
Ok(self.tcx.erase_regions(&result))
|
||||
let result = self.tcx.erase_regions(&result);
|
||||
|
||||
match self.tcx.lift_to_global(&result) {
|
||||
Some(result) => result,
|
||||
None => {
|
||||
span_bug!(span, "Uninferred types/regions in `{:?}`", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn projection_mode(&self) -> Reveal {
|
||||
@ -1702,17 +1668,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
let closure_ty = self.tcx.closure_type(def_id, substs);
|
||||
if self.normalize {
|
||||
let closure_ty = self.tcx.erase_regions(&closure_ty);
|
||||
|
||||
if !closure_ty.has_projection_types() {
|
||||
return closure_ty;
|
||||
}
|
||||
|
||||
self.normalize_projections_in(&closure_ty)
|
||||
} else {
|
||||
closure_ty
|
||||
}
|
||||
closure_ty
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
.unwrap()
|
||||
.subst(tcx, &penv.free_substs);
|
||||
|
||||
let result = tcx.normalizing_infer_ctxt(Reveal::ExactMatch).enter(|mut infcx| {
|
||||
let result = tcx.infer_ctxt(None, None, Reveal::ExactMatch).enter(|mut infcx| {
|
||||
// Normalize the trait reference, adding any obligations
|
||||
// that arise into the impl1 assumptions.
|
||||
let Normalized { value: impl1_trait_ref, obligations: normalization_obligations } = {
|
||||
@ -207,24 +207,27 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||
for oblig in obligations.into_iter() {
|
||||
fulfill_cx.register_predicate_obligation(&infcx, oblig);
|
||||
}
|
||||
match fulfill_cx.select_all_or_error(infcx) {
|
||||
Err(errors) => {
|
||||
// no dice!
|
||||
debug!("fulfill_implication: for impls on {:?} and {:?}, could not fulfill: {:?} given \
|
||||
{:?}",
|
||||
source_trait_ref,
|
||||
target_trait_ref,
|
||||
errors,
|
||||
infcx.parameter_environment.caller_bounds);
|
||||
Err(())
|
||||
}
|
||||
|
||||
if let Err(errors) = infcx.drain_fulfillment_cx(&mut fulfill_cx, &()) {
|
||||
// no dice!
|
||||
debug!("fulfill_implication: for impls on {:?} and {:?}, could not fulfill: {:?} given \
|
||||
{:?}",
|
||||
source_trait_ref,
|
||||
target_trait_ref,
|
||||
errors,
|
||||
infcx.parameter_environment.caller_bounds);
|
||||
Err(())
|
||||
} else {
|
||||
debug!("fulfill_implication: an impl for {:?} specializes {:?}",
|
||||
source_trait_ref,
|
||||
target_trait_ref);
|
||||
Ok(()) => {
|
||||
debug!("fulfill_implication: an impl for {:?} specializes {:?}",
|
||||
source_trait_ref,
|
||||
target_trait_ref);
|
||||
|
||||
// Now resolve the *substitution* we built for the target earlier, replacing
|
||||
// the inference variables inside with whatever we got from fulfillment.
|
||||
Ok(infcx.resolve_type_vars_if_possible(&target_substs))
|
||||
// Now resolve the *substitution* we built for the target earlier, replacing
|
||||
// the inference variables inside with whatever we got from fulfillment.
|
||||
Ok(infcx.resolve_type_vars_if_possible(&target_substs))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -953,8 +953,9 @@ impl<'tcx> TraitPredicate<'tcx> {
|
||||
_ =>
|
||||
None
|
||||
})
|
||||
.chain(iter::once(self.def_id()))
|
||||
.collect();
|
||||
DepNode::TraitSelect(self.def_id(), def_ids)
|
||||
DepNode::TraitSelect(def_ids)
|
||||
}
|
||||
|
||||
pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
|
||||
|
@ -691,7 +691,7 @@ impl LateLintPass for VariantSizeDifferences {
|
||||
if let hir::ItemEnum(ref enum_definition, ref gens) = it.node {
|
||||
if gens.ty_params.is_empty() { // sizes only make sense for non-generic types
|
||||
let t = cx.tcx.node_id_to_type(it.id);
|
||||
let layout = cx.tcx.normalizing_infer_ctxt(Reveal::All).enter(|infcx| {
|
||||
let layout = cx.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
|
||||
let ty = cx.tcx.erase_regions(&t);
|
||||
ty.layout(&infcx).unwrap_or_else(|e| {
|
||||
bug!("failed to get layout for `{}`: {}", t, e)
|
||||
|
@ -1128,7 +1128,7 @@ pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance
|
||||
|
||||
let fn_ty = ccx.tcx().lookup_item_type(instance.def).ty;
|
||||
let fn_ty = ccx.tcx().erase_regions(&fn_ty);
|
||||
let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), instance.substs, &fn_ty);
|
||||
let fn_ty = monomorphize::apply_param_substs(ccx.shared(), instance.substs, &fn_ty);
|
||||
|
||||
let sig = ccx.tcx().erase_late_bound_regions(fn_ty.fn_sig());
|
||||
let sig = ccx.tcx().normalize_associated_type(&sig);
|
||||
@ -1151,7 +1151,7 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
attributes::set_frame_pointer_elimination(ccx, llfndecl);
|
||||
|
||||
let ctor_ty = ccx.tcx().lookup_item_type(def_id).ty;
|
||||
let ctor_ty = monomorphize::apply_param_substs(ccx.tcx(), substs, &ctor_ty);
|
||||
let ctor_ty = monomorphize::apply_param_substs(ccx.shared(), substs, &ctor_ty);
|
||||
|
||||
let sig = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_sig());
|
||||
let sig = ccx.tcx().normalize_associated_type(&sig);
|
||||
@ -1894,7 +1894,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
|
||||
};
|
||||
|
||||
let codegen_units = time(time_passes, "codegen unit partitioning", || {
|
||||
partitioning::partition(scx.tcx(),
|
||||
partitioning::partition(scx,
|
||||
items.iter().cloned(),
|
||||
strategy,
|
||||
&inlining_map,
|
||||
|
@ -28,7 +28,7 @@ use base;
|
||||
use base::*;
|
||||
use build::*;
|
||||
use closure;
|
||||
use common::{self, Block, Result, CrateContext, FunctionContext};
|
||||
use common::{self, Block, Result, CrateContext, FunctionContext, SharedCrateContext};
|
||||
use consts;
|
||||
use debuginfo::DebugLoc;
|
||||
use declare;
|
||||
@ -37,7 +37,7 @@ use monomorphize::{self, Instance};
|
||||
use trans_item::TransItem;
|
||||
use type_of;
|
||||
use Disr;
|
||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc::ty::{self, Ty, TypeFoldable};
|
||||
use rustc::hir;
|
||||
|
||||
use syntax_pos::DUMMY_SP;
|
||||
@ -97,7 +97,7 @@ impl<'tcx> Callee<'tcx> {
|
||||
return Callee::trait_method(ccx, trait_id, def_id, substs);
|
||||
}
|
||||
|
||||
let fn_ty = def_ty(tcx, def_id, substs);
|
||||
let fn_ty = def_ty(ccx.shared(), def_id, substs);
|
||||
if let ty::TyFnDef(_, _, f) = fn_ty.sty {
|
||||
if f.abi == Abi::RustIntrinsic || f.abi == Abi::PlatformIntrinsic {
|
||||
return Callee {
|
||||
@ -155,20 +155,20 @@ impl<'tcx> Callee<'tcx> {
|
||||
vtable_closure.substs,
|
||||
trait_closure_kind);
|
||||
|
||||
let method_ty = def_ty(tcx, def_id, substs);
|
||||
let method_ty = def_ty(ccx.shared(), def_id, substs);
|
||||
Callee::ptr(llfn, method_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, vtable_fn_pointer.fn_ty);
|
||||
|
||||
let method_ty = def_ty(tcx, def_id, substs);
|
||||
let method_ty = def_ty(ccx.shared(), def_id, substs);
|
||||
Callee::ptr(llfn, method_ty)
|
||||
}
|
||||
traits::VtableObject(ref data) => {
|
||||
Callee {
|
||||
data: Virtual(tcx.get_vtable_index_of_object_method(data, def_id)),
|
||||
ty: def_ty(tcx, def_id, substs)
|
||||
ty: def_ty(ccx.shared(), def_id, substs)
|
||||
}
|
||||
}
|
||||
vtable => {
|
||||
@ -244,12 +244,12 @@ impl<'tcx> Callee<'tcx> {
|
||||
}
|
||||
|
||||
/// Given a DefId and some Substs, produces the monomorphic item type.
|
||||
fn def_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
fn def_ty<'a, 'tcx>(shared: &SharedCrateContext<'a, 'tcx>,
|
||||
def_id: DefId,
|
||||
substs: &'tcx Substs<'tcx>)
|
||||
-> Ty<'tcx> {
|
||||
let ty = tcx.lookup_item_type(def_id).ty;
|
||||
monomorphize::apply_param_substs(tcx, substs, &ty)
|
||||
let ty = shared.tcx().lookup_item_type(def_id).ty;
|
||||
monomorphize::apply_param_substs(shared, substs, &ty)
|
||||
}
|
||||
|
||||
/// Translates an adapter that implements the `Fn` trait for a fn
|
||||
@ -407,7 +407,7 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
let substs = tcx.normalize_associated_type(&substs);
|
||||
let instance = Instance::new(def_id, substs);
|
||||
let item_ty = ccx.tcx().lookup_item_type(def_id).ty;
|
||||
let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), substs, &item_ty);
|
||||
let fn_ty = monomorphize::apply_param_substs(ccx.shared(), substs, &item_ty);
|
||||
|
||||
if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
|
||||
return (llfn, fn_ty);
|
||||
|
@ -459,7 +459,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||
format!("Could not find MIR for closure: {:?}", def_id)
|
||||
});
|
||||
|
||||
let concrete_substs = monomorphize::apply_param_substs(self.scx.tcx(),
|
||||
let concrete_substs = monomorphize::apply_param_substs(self.scx,
|
||||
self.param_substs,
|
||||
&substs.func_substs);
|
||||
let concrete_substs = self.scx.tcx().erase_regions(&concrete_substs);
|
||||
@ -477,11 +477,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||
// have to instantiate all methods of the trait being cast to, so we
|
||||
// can build the appropriate vtable.
|
||||
mir::Rvalue::Cast(mir::CastKind::Unsize, ref operand, target_ty) => {
|
||||
let target_ty = monomorphize::apply_param_substs(self.scx.tcx(),
|
||||
let target_ty = monomorphize::apply_param_substs(self.scx,
|
||||
self.param_substs,
|
||||
&target_ty);
|
||||
let source_ty = operand.ty(self.mir, self.scx.tcx());
|
||||
let source_ty = monomorphize::apply_param_substs(self.scx.tcx(),
|
||||
let source_ty = monomorphize::apply_param_substs(self.scx,
|
||||
self.param_substs,
|
||||
&source_ty);
|
||||
let (source_ty, target_ty) = find_vtable_types_for_unsizing(self.scx,
|
||||
@ -508,7 +508,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||
assert!(can_have_local_instance(self.scx.tcx(), exchange_malloc_fn_def_id));
|
||||
let empty_substs = self.scx.empty_substs_for_def_id(exchange_malloc_fn_def_id);
|
||||
let exchange_malloc_fn_trans_item =
|
||||
create_fn_trans_item(self.scx.tcx(),
|
||||
create_fn_trans_item(self.scx,
|
||||
exchange_malloc_fn_def_id,
|
||||
empty_substs,
|
||||
self.param_substs);
|
||||
@ -531,7 +531,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||
let ty = lvalue.ty(self.mir, self.scx.tcx())
|
||||
.to_ty(self.scx.tcx());
|
||||
|
||||
let ty = monomorphize::apply_param_substs(self.scx.tcx(),
|
||||
let ty = monomorphize::apply_param_substs(self.scx,
|
||||
self.param_substs,
|
||||
&ty);
|
||||
assert!(ty.is_normalized_for_trans());
|
||||
@ -555,7 +555,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||
// references to `const` items
|
||||
if let mir::Literal::Item { def_id, substs } = constant.literal {
|
||||
let tcx = self.scx.tcx();
|
||||
let substs = monomorphize::apply_param_substs(tcx,
|
||||
let substs = monomorphize::apply_param_substs(self.scx,
|
||||
self.param_substs,
|
||||
&substs);
|
||||
|
||||
@ -613,7 +613,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||
// result in a translation item ...
|
||||
if can_result_in_trans_item(self.scx.tcx(), callee_def_id) {
|
||||
// ... and create one if it does.
|
||||
let trans_item = create_fn_trans_item(self.scx.tcx(),
|
||||
let trans_item = create_fn_trans_item(self.scx,
|
||||
callee_def_id,
|
||||
callee_substs,
|
||||
self.param_substs);
|
||||
@ -670,7 +670,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||
if is_drop_in_place_intrinsic(tcx, def_id, bare_fn_ty) => {
|
||||
let operand_ty = args[0].ty(self.mir, tcx);
|
||||
if let ty::TyRawPtr(mt) = operand_ty.sty {
|
||||
let operand_ty = monomorphize::apply_param_substs(tcx,
|
||||
let operand_ty = monomorphize::apply_param_substs(self.scx,
|
||||
self.param_substs,
|
||||
&mt.ty);
|
||||
let ty = glue::get_drop_glue_type(tcx, operand_ty);
|
||||
@ -732,7 +732,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
assert!(can_have_local_instance(scx.tcx(), exchange_free_fn_def_id));
|
||||
let fn_substs = scx.empty_substs_for_def_id(exchange_free_fn_def_id);
|
||||
let exchange_free_fn_trans_item =
|
||||
create_fn_trans_item(scx.tcx(),
|
||||
create_fn_trans_item(scx,
|
||||
exchange_free_fn_def_id,
|
||||
fn_substs,
|
||||
Substs::empty(scx.tcx()));
|
||||
@ -769,7 +769,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
};
|
||||
|
||||
if can_have_local_instance(scx.tcx(), destructor_did) {
|
||||
let trans_item = create_fn_trans_item(scx.tcx(),
|
||||
let trans_item = create_fn_trans_item(scx,
|
||||
destructor_did,
|
||||
substs,
|
||||
Substs::empty(scx.tcx()));
|
||||
@ -800,7 +800,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
ty::TyStruct(ref adt_def, substs) |
|
||||
ty::TyEnum(ref adt_def, substs) => {
|
||||
for field in adt_def.all_fields() {
|
||||
let field_type = monomorphize::apply_param_substs(scx.tcx(),
|
||||
let field_type = monomorphize::apply_param_substs(scx,
|
||||
substs,
|
||||
&field.unsubst_ty());
|
||||
let field_type = glue::get_drop_glue_type(scx.tcx(), field_type);
|
||||
@ -894,8 +894,7 @@ fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
callee_substs,
|
||||
param_substs);
|
||||
|
||||
|
||||
let rcvr_substs = monomorphize::apply_param_substs(tcx,
|
||||
let rcvr_substs = monomorphize::apply_param_substs(scx,
|
||||
param_substs,
|
||||
&callee_substs);
|
||||
let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
|
||||
@ -1016,11 +1015,13 @@ fn find_vtable_types_for_unsizing<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn create_fn_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
fn create_fn_trans_item<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
def_id: DefId,
|
||||
fn_substs: &'tcx Substs<'tcx>,
|
||||
param_substs: &'tcx Substs<'tcx>)
|
||||
-> TransItem<'tcx> {
|
||||
let tcx = scx.tcx();
|
||||
|
||||
debug!("create_fn_trans_item(def_id={}, fn_substs={:?}, param_substs={:?})",
|
||||
def_id_to_string(tcx, def_id),
|
||||
fn_substs,
|
||||
@ -1029,7 +1030,7 @@ fn create_fn_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
// We only get here, if fn_def_id either designates a local item or
|
||||
// an inlineable external item. Non-inlineable external items are
|
||||
// ignored because we don't want to generate any code for them.
|
||||
let concrete_substs = monomorphize::apply_param_substs(tcx,
|
||||
let concrete_substs = monomorphize::apply_param_substs(scx,
|
||||
param_substs,
|
||||
&fn_substs);
|
||||
assert!(concrete_substs.is_normalized_for_trans());
|
||||
@ -1063,7 +1064,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a,
|
||||
// create translation items
|
||||
.filter_map(|impl_method| {
|
||||
if can_have_local_instance(scx.tcx(), impl_method.method.def_id) {
|
||||
Some(create_fn_trans_item(scx.tcx(),
|
||||
Some(create_fn_trans_item(scx,
|
||||
impl_method.method.def_id,
|
||||
impl_method.substs,
|
||||
Substs::empty(scx.tcx())))
|
||||
@ -1114,7 +1115,7 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> {
|
||||
|
||||
hir::ItemImpl(..) => {
|
||||
if self.mode == TransItemCollectionMode::Eager {
|
||||
create_trans_items_for_default_impls(self.scx.tcx(),
|
||||
create_trans_items_for_default_impls(self.scx,
|
||||
item,
|
||||
self.output);
|
||||
}
|
||||
@ -1202,9 +1203,10 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> {
|
||||
}
|
||||
}
|
||||
|
||||
fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
item: &'tcx hir::Item,
|
||||
output: &mut Vec<TransItem<'tcx>>) {
|
||||
let tcx = scx.tcx();
|
||||
match item.node {
|
||||
hir::ItemImpl(_,
|
||||
_,
|
||||
@ -1255,7 +1257,7 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
if can_have_local_instance(tcx, method.def_id) {
|
||||
let empty_substs = tcx.erase_regions(&mth.substs);
|
||||
let item = create_fn_trans_item(tcx,
|
||||
let item = create_fn_trans_item(scx,
|
||||
method.def_id,
|
||||
callee_substs,
|
||||
empty_substs);
|
||||
|
@ -350,7 +350,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
|
||||
pub fn monomorphize<T>(&self, value: &T) -> T
|
||||
where T: TransNormalize<'tcx>
|
||||
{
|
||||
monomorphize::apply_param_substs(self.ccx.tcx(),
|
||||
monomorphize::apply_param_substs(self.ccx.shared(),
|
||||
self.param_substs,
|
||||
value)
|
||||
}
|
||||
@ -519,7 +519,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
|
||||
pub fn monomorphize<T>(&self, value: &T) -> T
|
||||
where T: TransNormalize<'tcx>
|
||||
{
|
||||
monomorphize::apply_param_substs(self.tcx(),
|
||||
monomorphize::apply_param_substs(self.fcx.ccx.shared(),
|
||||
self.fcx.param_substs,
|
||||
value)
|
||||
}
|
||||
@ -955,7 +955,7 @@ pub fn fulfill_obligation<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
|
||||
// Do the initial selection for the obligation. This yields the
|
||||
// shallow result we are looking for -- that is, what specific impl.
|
||||
tcx.normalizing_infer_ctxt(Reveal::All).enter(|infcx| {
|
||||
tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
|
||||
let mut selcx = SelectionContext::new(&infcx);
|
||||
|
||||
let obligation_cause = traits::ObligationCause::misc(span,
|
||||
@ -1014,7 +1014,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
debug!("normalize_and_test_predicates(predicates={:?})",
|
||||
predicates);
|
||||
|
||||
tcx.normalizing_infer_ctxt(Reveal::All).enter(|infcx| {
|
||||
tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
|
||||
let mut selcx = SelectionContext::new(&infcx);
|
||||
let mut fulfill_cx = traits::FulfillmentContext::new();
|
||||
let cause = traits::ObligationCause::dummy();
|
||||
@ -1028,7 +1028,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
fulfill_cx.register_predicate_obligation(&infcx, obligation);
|
||||
}
|
||||
|
||||
infcx.drain_fulfillment_cx(&mut fulfill_cx, &()).is_ok()
|
||||
fulfill_cx.select_all_or_error(&infcx).is_ok()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,7 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
|
||||
|
||||
translation_items: RefCell<FnvHashSet<TransItem<'tcx>>>,
|
||||
trait_cache: RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>,
|
||||
project_cache: RefCell<DepTrackingMap<ProjectionCache<'tcx>>>,
|
||||
}
|
||||
|
||||
/// The local portion of a `CrateContext`. There is one `LocalCrateContext`
|
||||
@ -195,6 +196,46 @@ impl<'tcx> DepTrackingMapConfig for MirCache<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
// # Global Cache
|
||||
|
||||
pub struct ProjectionCache<'gcx> {
|
||||
data: PhantomData<&'gcx ()>
|
||||
}
|
||||
|
||||
impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> {
|
||||
type Key = Ty<'gcx>;
|
||||
type Value = Ty<'gcx>;
|
||||
fn to_dep_node(key: &Self::Key) -> DepNode<DefId> {
|
||||
// Ideally, we'd just put `key` into the dep-node, but we
|
||||
// can't put full types in there. So just collect up all the
|
||||
// def-ids of structs/enums as well as any traits that we
|
||||
// project out of. It doesn't matter so much what we do here,
|
||||
// except that if we are too coarse, we'll create overly
|
||||
// coarse edges between impls and the trans. For example, if
|
||||
// we just used the def-id of things we are projecting out of,
|
||||
// then the key for `<Foo as SomeTrait>::T` and `<Bar as
|
||||
// SomeTrait>::T` would both share a dep-node
|
||||
// (`TraitSelect(SomeTrait)`), and hence the impls for both
|
||||
// `Foo` and `Bar` would be considered inputs. So a change to
|
||||
// `Bar` would affect things that just normalized `Foo`.
|
||||
// Anyway, this heuristic is not ideal, but better than
|
||||
// nothing.
|
||||
let def_ids: Vec<DefId> =
|
||||
key.walk()
|
||||
.filter_map(|t| match t.sty {
|
||||
ty::TyStruct(adt_def, _) |
|
||||
ty::TyEnum(adt_def, _) =>
|
||||
Some(adt_def.did),
|
||||
ty::TyProjection(ref proj) =>
|
||||
Some(proj.trait_ref.def_id),
|
||||
_ =>
|
||||
None
|
||||
})
|
||||
.collect();
|
||||
DepNode::TraitSelect(def_ids)
|
||||
}
|
||||
}
|
||||
|
||||
/// This list owns a number of LocalCrateContexts and binds them to their common
|
||||
/// SharedCrateContext. This type just exists as a convenience, something to
|
||||
/// pass around all LocalCrateContexts with and get an iterator over them.
|
||||
@ -496,6 +537,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
|
||||
use_dll_storage_attrs: use_dll_storage_attrs,
|
||||
translation_items: RefCell::new(FnvHashSet()),
|
||||
trait_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())),
|
||||
project_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())),
|
||||
}
|
||||
}
|
||||
|
||||
@ -519,6 +561,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
|
||||
&self.trait_cache
|
||||
}
|
||||
|
||||
pub fn project_cache(&self) -> &RefCell<DepTrackingMap<ProjectionCache<'tcx>>> {
|
||||
&self.project_cache
|
||||
}
|
||||
|
||||
pub fn link_meta<'a>(&'a self) -> &'a LinkMeta {
|
||||
&self.link_meta
|
||||
}
|
||||
@ -950,7 +996,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn layout_of(&self, ty: Ty<'tcx>) -> &'tcx ty::layout::Layout {
|
||||
self.tcx().normalizing_infer_ctxt(traits::Reveal::All).enter(|infcx| {
|
||||
self.tcx().infer_ctxt(None, None, traits::Reveal::All).enter(|infcx| {
|
||||
ty.layout(&infcx).unwrap_or_else(|e| {
|
||||
bug!("failed to get layout for `{}`: {}", ty, e);
|
||||
})
|
||||
|
@ -414,7 +414,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
if cx.tcx().trait_id_of_impl(impl_def_id).is_none() {
|
||||
let impl_self_ty = cx.tcx().lookup_item_type(impl_def_id).ty;
|
||||
let impl_self_ty = cx.tcx().erase_regions(&impl_self_ty);
|
||||
let impl_self_ty = monomorphize::apply_param_substs(cx.tcx(),
|
||||
let impl_self_ty = monomorphize::apply_param_substs(cx.shared(),
|
||||
instance.substs,
|
||||
&impl_self_ty);
|
||||
|
||||
|
@ -113,7 +113,7 @@ pub fn get_drop_glue_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
match t.sty {
|
||||
ty::TyBox(typ) if !type_needs_drop(tcx, typ)
|
||||
&& type_is_sized(tcx, typ) => {
|
||||
tcx.normalizing_infer_ctxt(traits::Reveal::All).enter(|infcx| {
|
||||
tcx.infer_ctxt(None, None, traits::Reveal::All).enter(|infcx| {
|
||||
let layout = t.layout(&infcx).unwrap();
|
||||
if layout.size(&tcx.data_layout).bytes() == 0 {
|
||||
// `Box<ZeroSizeType>` does not allocate.
|
||||
|
@ -314,7 +314,7 @@ pub fn get_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
match trait_def.ancestors(impl_def_id).fn_defs(tcx, name).next() {
|
||||
Some(node_item) => {
|
||||
let substs = tcx.normalizing_infer_ctxt(Reveal::All).enter(|infcx| {
|
||||
let substs = tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
|
||||
let substs = substs.rebase_onto(tcx, trait_def_id, impl_substs);
|
||||
let substs = traits::translate_substs(&infcx, impl_def_id,
|
||||
substs, node_item.node);
|
||||
|
@ -258,7 +258,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
fn monomorphize<T>(&self, value: &T) -> T
|
||||
where T: TransNormalize<'tcx>
|
||||
{
|
||||
monomorphize::apply_param_substs(self.ccx.tcx(),
|
||||
monomorphize::apply_param_substs(self.ccx.shared(),
|
||||
self.substs,
|
||||
value)
|
||||
}
|
||||
|
@ -8,13 +8,14 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use common::*;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::infer::TransNormalize;
|
||||
use rustc::ty::fold::{TypeFolder, TypeFoldable};
|
||||
use rustc::ty::subst::{Subst, Substs};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use common::*;
|
||||
use rustc::util::ppaux;
|
||||
|
||||
use rustc::util::common::MemoizationMap;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
@ -42,14 +43,17 @@ impl<'tcx> Instance<'tcx> {
|
||||
|
||||
/// Monomorphizes a type from the AST by first applying the in-scope
|
||||
/// substitutions and then normalizing any associated types.
|
||||
pub fn apply_param_substs<'a, 'tcx, T>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
pub fn apply_param_substs<'a, 'tcx, T>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
param_substs: &Substs<'tcx>,
|
||||
value: &T)
|
||||
-> T
|
||||
where T: TransNormalize<'tcx>
|
||||
{
|
||||
let tcx = scx.tcx();
|
||||
debug!("apply_param_substs(param_substs={:?}, value={:?})", param_substs, value);
|
||||
let substituted = value.subst(tcx, param_substs);
|
||||
tcx.normalize_associated_type(&substituted)
|
||||
let substituted = scx.tcx().erase_regions(&substituted);
|
||||
AssociatedTypeNormalizer::new(scx).fold(&substituted)
|
||||
}
|
||||
|
||||
|
||||
@ -61,3 +65,40 @@ pub fn field_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
{
|
||||
tcx.normalize_associated_type(&f.ty(tcx, param_substs))
|
||||
}
|
||||
|
||||
struct AssociatedTypeNormalizer<'a, 'b: 'a, 'gcx: 'b> {
|
||||
shared: &'a SharedCrateContext<'b, 'gcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'gcx> AssociatedTypeNormalizer<'a, 'b, 'gcx> {
|
||||
fn new(shared: &'a SharedCrateContext<'b, 'gcx>) -> Self {
|
||||
AssociatedTypeNormalizer {
|
||||
shared: shared,
|
||||
}
|
||||
}
|
||||
|
||||
fn fold<T:TypeFoldable<'gcx>>(&mut self, value: &T) -> T {
|
||||
if !value.has_projection_types() {
|
||||
value.clone()
|
||||
} else {
|
||||
value.fold_with(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'b, 'gcx> {
|
||||
fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'gcx> {
|
||||
self.shared.tcx()
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty<'gcx>) -> Ty<'gcx> {
|
||||
if !ty.has_projection_types() {
|
||||
ty
|
||||
} else {
|
||||
self.shared.project_cache().memoize(ty, || {
|
||||
debug!("AssociatedTypeNormalizer: ty={:?}", ty);
|
||||
self.shared.tcx().normalize_associated_type(&ty)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -117,6 +117,7 @@
|
||||
//! inlining, even when they are not marked #[inline].
|
||||
|
||||
use collector::InliningMap;
|
||||
use context::SharedCrateContext;
|
||||
use llvm;
|
||||
use monomorphize;
|
||||
use rustc::dep_graph::{DepNode, WorkProductId};
|
||||
@ -250,7 +251,7 @@ impl<'tcx> CodegenUnit<'tcx> {
|
||||
// Anything we can't find a proper codegen unit for goes into this.
|
||||
const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
|
||||
|
||||
pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
pub fn partition<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
trans_items: I,
|
||||
strategy: PartitioningStrategy,
|
||||
inlining_map: &InliningMap<'tcx>,
|
||||
@ -258,6 +259,8 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
-> Vec<CodegenUnit<'tcx>>
|
||||
where I: Iterator<Item = TransItem<'tcx>>
|
||||
{
|
||||
let tcx = scx.tcx();
|
||||
|
||||
if let PartitioningStrategy::FixedUnitCount(1) = strategy {
|
||||
// If there is only a single codegen-unit, we can use a very simple
|
||||
// scheme and don't have to bother with doing much analysis.
|
||||
@ -267,7 +270,7 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
// In the first step, we place all regular translation items into their
|
||||
// respective 'home' codegen unit. Regular translation items are all
|
||||
// functions and statics defined in the local crate.
|
||||
let mut initial_partitioning = place_root_translation_items(tcx,
|
||||
let mut initial_partitioning = place_root_translation_items(scx,
|
||||
trans_items,
|
||||
reachable);
|
||||
|
||||
@ -306,12 +309,13 @@ struct PreInliningPartitioning<'tcx> {
|
||||
|
||||
struct PostInliningPartitioning<'tcx>(Vec<CodegenUnit<'tcx>>);
|
||||
|
||||
fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
fn place_root_translation_items<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
trans_items: I,
|
||||
_reachable: &NodeSet)
|
||||
-> PreInliningPartitioning<'tcx>
|
||||
where I: Iterator<Item = TransItem<'tcx>>
|
||||
{
|
||||
let tcx = scx.tcx();
|
||||
let mut roots = FnvHashSet();
|
||||
let mut codegen_units = FnvHashMap();
|
||||
|
||||
@ -319,7 +323,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
let is_root = !trans_item.is_instantiated_only_on_demand();
|
||||
|
||||
if is_root {
|
||||
let characteristic_def_id = characteristic_def_id_of_trans_item(tcx, trans_item);
|
||||
let characteristic_def_id = characteristic_def_id_of_trans_item(scx, trans_item);
|
||||
let is_volatile = trans_item.is_generic_fn();
|
||||
|
||||
let codegen_unit_name = match characteristic_def_id {
|
||||
@ -477,9 +481,10 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit
|
||||
}
|
||||
}
|
||||
|
||||
fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
fn characteristic_def_id_of_trans_item<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
trans_item: TransItem<'tcx>)
|
||||
-> Option<DefId> {
|
||||
let tcx = scx.tcx();
|
||||
match trans_item {
|
||||
TransItem::Fn(instance) => {
|
||||
// If this is a method, we want to put it into the same module as
|
||||
@ -497,7 +502,7 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
// self-type is:
|
||||
let impl_self_ty = tcx.lookup_item_type(impl_def_id).ty;
|
||||
let impl_self_ty = tcx.erase_regions(&impl_self_ty);
|
||||
let impl_self_ty = monomorphize::apply_param_substs(tcx,
|
||||
let impl_self_ty = monomorphize::apply_param_substs(scx,
|
||||
instance.substs,
|
||||
&impl_self_ty);
|
||||
|
||||
|
@ -176,7 +176,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||
|
||||
let item_ty = ccx.tcx().lookup_item_type(instance.def).ty;
|
||||
let item_ty = ccx.tcx().erase_regions(&item_ty);
|
||||
let mono_ty = monomorphize::apply_param_substs(ccx.tcx(), instance.substs, &item_ty);
|
||||
let mono_ty = monomorphize::apply_param_substs(ccx.shared(), instance.substs, &item_ty);
|
||||
|
||||
let attrs = ccx.tcx().get_attrs(instance.def);
|
||||
let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty);
|
||||
|
Loading…
Reference in New Issue
Block a user