Skip to content

Commit 6d86f81

Browse files
committed
move the uses of the trans caches into rustc::traits
This makes these routines more readily available for other bits of code. It also will help when refactoring.
1 parent 8552745 commit 6d86f81

File tree

6 files changed

+164
-154
lines changed

6 files changed

+164
-154
lines changed

src/librustc/traits/trans/mod.rs

+143-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,154 @@
1+
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// This file contains various trait resolution methods used by trans.
12+
// They all assume regions can be erased and monomorphic types. It
13+
// seems likely that they should eventually be merged into more
14+
// general routines.
15+
116
use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
217
use hir::def_id::DefId;
18+
use infer::TransNormalize;
319
use std::cell::RefCell;
420
use std::marker::PhantomData;
5-
use traits::Vtable;
6-
use ty::{self, Ty};
21+
use syntax::ast;
22+
use syntax_pos::Span;
23+
use traits::{FulfillmentContext, Obligation, ObligationCause, Reveal, SelectionContext, Vtable};
24+
use ty::{self, Ty, TyCtxt};
25+
use ty::subst::{Subst, Substs};
26+
use ty::fold::{TypeFoldable, TypeFolder};
27+
use util::common::MemoizationMap;
28+
29+
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
30+
/// Attempts to resolve an obligation to a vtable.. The result is
31+
/// a shallow vtable resolution -- meaning that we do not
32+
/// (necessarily) resolve all nested obligations on the impl. Note
33+
/// that type check should guarantee to us that all nested
34+
/// obligations *could be* resolved if we wanted to.
35+
pub fn trans_fulfill_obligation(self,
36+
span: Span,
37+
trait_ref: ty::PolyTraitRef<'tcx>)
38+
-> Vtable<'tcx, ()>
39+
{
40+
// Remove any references to regions; this helps improve caching.
41+
let trait_ref = self.erase_regions(&trait_ref);
42+
43+
self.trans_trait_caches.trait_cache.memoize(trait_ref, || {
44+
debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
45+
trait_ref, trait_ref.def_id());
46+
47+
// Do the initial selection for the obligation. This yields the
48+
// shallow result we are looking for -- that is, what specific impl.
49+
self.infer_ctxt((), Reveal::All).enter(|infcx| {
50+
let mut selcx = SelectionContext::new(&infcx);
51+
52+
let obligation_cause = ObligationCause::misc(span,
53+
ast::DUMMY_NODE_ID);
54+
let obligation = Obligation::new(obligation_cause,
55+
trait_ref.to_poly_trait_predicate());
56+
57+
let selection = match selcx.select(&obligation) {
58+
Ok(Some(selection)) => selection,
59+
Ok(None) => {
60+
// Ambiguity can happen when monomorphizing during trans
61+
// expands to some humongo type that never occurred
62+
// statically -- this humongo type can then overflow,
63+
// leading to an ambiguous result. So report this as an
64+
// overflow bug, since I believe this is the only case
65+
// where ambiguity can result.
66+
debug!("Encountered ambiguity selecting `{:?}` during trans, \
67+
presuming due to overflow",
68+
trait_ref);
69+
self.sess.span_fatal(span,
70+
"reached the recursion limit during monomorphization \
71+
(selection ambiguity)");
72+
}
73+
Err(e) => {
74+
span_bug!(span, "Encountered error `{:?}` selecting `{:?}` during trans",
75+
e, trait_ref)
76+
}
77+
};
78+
79+
debug!("fulfill_obligation: selection={:?}", selection);
80+
81+
// Currently, we use a fulfillment context to completely resolve
82+
// all nested obligations. This is because they can inform the
83+
// inference of the impl's type parameters.
84+
let mut fulfill_cx = FulfillmentContext::new();
85+
let vtable = selection.map(|predicate| {
86+
debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate);
87+
fulfill_cx.register_predicate_obligation(&infcx, predicate);
88+
});
89+
let vtable = infcx.drain_fulfillment_cx_or_panic(span, &mut fulfill_cx, &vtable);
90+
91+
info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
92+
vtable
93+
})
94+
})
95+
}
96+
97+
/// Monomorphizes a type from the AST by first applying the in-scope
98+
/// substitutions and then normalizing any associated types.
99+
pub fn trans_apply_param_substs<T>(self,
100+
param_substs: &Substs<'tcx>,
101+
value: &T)
102+
-> T
103+
where T: TransNormalize<'tcx>
104+
{
105+
debug!("apply_param_substs(param_substs={:?}, value={:?})", param_substs, value);
106+
let substituted = value.subst(self, param_substs);
107+
let substituted = self.erase_regions(&substituted);
108+
AssociatedTypeNormalizer::new(self).fold(&substituted)
109+
}
110+
}
111+
112+
struct AssociatedTypeNormalizer<'a, 'gcx: 'a> {
113+
tcx: TyCtxt<'a, 'gcx, 'gcx>,
114+
}
115+
116+
impl<'a, 'gcx> AssociatedTypeNormalizer<'a, 'gcx> {
117+
fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) -> Self {
118+
AssociatedTypeNormalizer { tcx }
119+
}
120+
121+
fn fold<T:TypeFoldable<'gcx>>(&mut self, value: &T) -> T {
122+
if !value.has_projection_types() {
123+
value.clone()
124+
} else {
125+
value.fold_with(self)
126+
}
127+
}
128+
}
129+
130+
impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> {
131+
fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'gcx> {
132+
self.tcx
133+
}
134+
135+
fn fold_ty(&mut self, ty: Ty<'gcx>) -> Ty<'gcx> {
136+
if !ty.has_projection_types() {
137+
ty
138+
} else {
139+
self.tcx.trans_trait_caches.project_cache.memoize(ty, || {
140+
debug!("AssociatedTypeNormalizer: ty={:?}", ty);
141+
self.tcx.normalize_associated_type(&ty)
142+
})
143+
}
144+
}
145+
}
7146

8147
/// Specializes caches used in trans -- in particular, they assume all
9148
/// types are fully monomorphized and that free regions can be erased.
10149
pub struct TransTraitCaches<'tcx> {
11-
pub trait_cache: RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>,
12-
pub project_cache: RefCell<DepTrackingMap<ProjectionCache<'tcx>>>,
150+
trait_cache: RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>,
151+
project_cache: RefCell<DepTrackingMap<ProjectionCache<'tcx>>>,
13152
}
14153

15154
impl<'tcx> TransTraitCaches<'tcx> {

src/librustc_trans/collector.rs

+10-18
Original file line numberDiff line numberDiff line change
@@ -467,13 +467,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
467467
// have to instantiate all methods of the trait being cast to, so we
468468
// can build the appropriate vtable.
469469
mir::Rvalue::Cast(mir::CastKind::Unsize, ref operand, target_ty) => {
470-
let target_ty = monomorphize::apply_param_substs(self.scx,
471-
self.param_substs,
472-
&target_ty);
470+
let target_ty = self.scx.tcx().trans_apply_param_substs(self.param_substs,
471+
&target_ty);
473472
let source_ty = operand.ty(self.mir, self.scx.tcx());
474-
let source_ty = monomorphize::apply_param_substs(self.scx,
475-
self.param_substs,
476-
&source_ty);
473+
let source_ty = self.scx.tcx().trans_apply_param_substs(self.param_substs,
474+
&source_ty);
477475
let (source_ty, target_ty) = find_vtable_types_for_unsizing(self.scx,
478476
source_ty,
479477
target_ty);
@@ -489,10 +487,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
489487
}
490488
mir::Rvalue::Cast(mir::CastKind::ReifyFnPointer, ref operand, _) => {
491489
let fn_ty = operand.ty(self.mir, self.scx.tcx());
492-
let fn_ty = monomorphize::apply_param_substs(
493-
self.scx,
494-
self.param_substs,
495-
&fn_ty);
490+
let fn_ty = self.scx.tcx().trans_apply_param_substs(self.param_substs,
491+
&fn_ty);
496492
visit_fn_use(self.scx, fn_ty, false, &mut self.output);
497493
}
498494
mir::Rvalue::Cast(mir::CastKind::ClosureFnPointer, ref operand, _) => {
@@ -534,9 +530,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
534530
}
535531

536532
if let mir::Literal::Item { def_id, substs } = constant.literal {
537-
let substs = monomorphize::apply_param_substs(self.scx,
538-
self.param_substs,
539-
&substs);
533+
let substs = self.scx.tcx().trans_apply_param_substs(self.param_substs,
534+
&substs);
540535
let instance = monomorphize::resolve(self.scx, def_id, substs);
541536
collect_neighbours(self.scx, instance, self.output);
542537
}
@@ -552,17 +547,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
552547
match *kind {
553548
mir::TerminatorKind::Call { ref func, .. } => {
554549
let callee_ty = func.ty(self.mir, tcx);
555-
let callee_ty = monomorphize::apply_param_substs(
556-
self.scx, self.param_substs, &callee_ty);
550+
let callee_ty = tcx.trans_apply_param_substs(self.param_substs, &callee_ty);
557551
visit_fn_use(self.scx, callee_ty, true, &mut self.output);
558552
}
559553
mir::TerminatorKind::Drop { ref location, .. } |
560554
mir::TerminatorKind::DropAndReplace { ref location, .. } => {
561555
let ty = location.ty(self.mir, self.scx.tcx())
562556
.to_ty(self.scx.tcx());
563-
let ty = monomorphize::apply_param_substs(self.scx,
564-
self.param_substs,
565-
&ty);
557+
let ty = tcx.trans_apply_param_substs(self.param_substs, &ty);
566558
visit_drop_use(self.scx, ty, true, self.output);
567559
}
568560
mir::TerminatorKind::Goto { .. } |

src/librustc_trans/common.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ pub fn def_ty<'a, 'tcx>(shared: &SharedCrateContext<'a, 'tcx>,
564564
-> Ty<'tcx>
565565
{
566566
let ty = shared.tcx().item_type(def_id);
567-
monomorphize::apply_param_substs(shared, substs, &ty)
567+
shared.tcx().trans_apply_param_substs(substs, &ty)
568568
}
569569

570570
/// Return the substituted type of an instance.
@@ -573,5 +573,5 @@ pub fn instance_ty<'a, 'tcx>(shared: &SharedCrateContext<'a, 'tcx>,
573573
-> Ty<'tcx>
574574
{
575575
let ty = instance.def.def_ty(shared.tcx());
576-
monomorphize::apply_param_substs(shared, instance.substs, &ty)
576+
shared.tcx().trans_apply_param_substs(instance.substs, &ty)
577577
}

src/librustc_trans/mir/constant.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
260260
fn monomorphize<T>(&self, value: &T) -> T
261261
where T: TransNormalize<'tcx>
262262
{
263-
monomorphize::apply_param_substs(self.ccx.shared(),
264-
self.substs,
265-
value)
263+
self.ccx.tcx().trans_apply_param_substs(self.substs, value)
266264
}
267265

268266
fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {

src/librustc_trans/mir/mod.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use base;
2222
use builder::Builder;
2323
use common::{self, CrateContext, Funclet};
2424
use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext};
25-
use monomorphize::{self, Instance};
25+
use monomorphize::Instance;
2626
use abi::FnType;
2727
use type_of;
2828

@@ -102,8 +102,9 @@ pub struct MirContext<'a, 'tcx:'a> {
102102

103103
impl<'a, 'tcx> MirContext<'a, 'tcx> {
104104
pub fn monomorphize<T>(&self, value: &T) -> T
105-
where T: TransNormalize<'tcx> {
106-
monomorphize::apply_param_substs(self.ccx.shared(), self.param_substs, value)
105+
where T: TransNormalize<'tcx>
106+
{
107+
self.ccx.tcx().trans_apply_param_substs(self.param_substs, value)
107108
}
108109

109110
pub fn set_debug_loc(&mut self, bcx: &Builder, source_info: mir::SourceInfo) {

0 commit comments

Comments
 (0)