about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/traits/trans/mod.rs147
-rw-r--r--src/librustc_trans/collector.rs28
-rw-r--r--src/librustc_trans/common.rs4
-rw-r--r--src/librustc_trans/mir/constant.rs4
-rw-r--r--src/librustc_trans/mir/mod.rs7
-rw-r--r--src/librustc_trans/monomorphize.rs128
6 files changed, 164 insertions, 154 deletions
diff --git a/src/librustc/traits/trans/mod.rs b/src/librustc/traits/trans/mod.rs
index 8517f573e60..e38306aed2a 100644
--- a/src/librustc/traits/trans/mod.rs
+++ b/src/librustc/traits/trans/mod.rs
@@ -1,15 +1,154 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file contains various trait resolution methods used by trans.
+// They all assume regions can be erased and monomorphic types.  It
+// seems likely that they should eventually be merged into more
+// general routines.
+
 use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
 use hir::def_id::DefId;
+use infer::TransNormalize;
 use std::cell::RefCell;
 use std::marker::PhantomData;
-use traits::Vtable;
-use ty::{self, Ty};
+use syntax::ast;
+use syntax_pos::Span;
+use traits::{FulfillmentContext, Obligation, ObligationCause, Reveal, SelectionContext, Vtable};
+use ty::{self, Ty, TyCtxt};
+use ty::subst::{Subst, Substs};
+use ty::fold::{TypeFoldable, TypeFolder};
+use util::common::MemoizationMap;
+
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
+    /// Attempts to resolve an obligation to a vtable.. The result is
+    /// a shallow vtable resolution -- meaning that we do not
+    /// (necessarily) resolve all nested obligations on the impl. Note
+    /// that type check should guarantee to us that all nested
+    /// obligations *could be* resolved if we wanted to.
+    pub fn trans_fulfill_obligation(self,
+                                    span: Span,
+                                    trait_ref: ty::PolyTraitRef<'tcx>)
+                                    -> Vtable<'tcx, ()>
+    {
+        // Remove any references to regions; this helps improve caching.
+        let trait_ref = self.erase_regions(&trait_ref);
+
+        self.trans_trait_caches.trait_cache.memoize(trait_ref, || {
+            debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
+                   trait_ref, trait_ref.def_id());
+
+            // Do the initial selection for the obligation. This yields the
+            // shallow result we are looking for -- that is, what specific impl.
+            self.infer_ctxt((), Reveal::All).enter(|infcx| {
+                let mut selcx = SelectionContext::new(&infcx);
+
+                let obligation_cause = ObligationCause::misc(span,
+                                                             ast::DUMMY_NODE_ID);
+                let obligation = Obligation::new(obligation_cause,
+                                                 trait_ref.to_poly_trait_predicate());
+
+                let selection = match selcx.select(&obligation) {
+                    Ok(Some(selection)) => selection,
+                    Ok(None) => {
+                        // Ambiguity can happen when monomorphizing during trans
+                        // expands to some humongo type that never occurred
+                        // statically -- this humongo type can then overflow,
+                        // leading to an ambiguous result. So report this as an
+                        // overflow bug, since I believe this is the only case
+                        // where ambiguity can result.
+                        debug!("Encountered ambiguity selecting `{:?}` during trans, \
+                                presuming due to overflow",
+                               trait_ref);
+                        self.sess.span_fatal(span,
+                                            "reached the recursion limit during monomorphization \
+                                             (selection ambiguity)");
+                    }
+                    Err(e) => {
+                        span_bug!(span, "Encountered error `{:?}` selecting `{:?}` during trans",
+                                  e, trait_ref)
+                    }
+                };
+
+                debug!("fulfill_obligation: selection={:?}", selection);
+
+                // Currently, we use a fulfillment context to completely resolve
+                // all nested obligations. This is because they can inform the
+                // inference of the impl's type parameters.
+                let mut fulfill_cx = FulfillmentContext::new();
+                let vtable = selection.map(|predicate| {
+                    debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate);
+                    fulfill_cx.register_predicate_obligation(&infcx, predicate);
+                });
+                let vtable = infcx.drain_fulfillment_cx_or_panic(span, &mut fulfill_cx, &vtable);
+
+                info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
+                vtable
+            })
+        })
+    }
+
+    /// Monomorphizes a type from the AST by first applying the in-scope
+    /// substitutions and then normalizing any associated types.
+    pub fn trans_apply_param_substs<T>(self,
+                                       param_substs: &Substs<'tcx>,
+                                       value: &T)
+                                       -> T
+        where T: TransNormalize<'tcx>
+    {
+        debug!("apply_param_substs(param_substs={:?}, value={:?})", param_substs, value);
+        let substituted = value.subst(self, param_substs);
+        let substituted = self.erase_regions(&substituted);
+        AssociatedTypeNormalizer::new(self).fold(&substituted)
+    }
+}
+
+struct AssociatedTypeNormalizer<'a, 'gcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'gcx>,
+}
+
+impl<'a, 'gcx> AssociatedTypeNormalizer<'a, 'gcx> {
+    fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) -> Self {
+        AssociatedTypeNormalizer { tcx }
+    }
+
+    fn fold<T:TypeFoldable<'gcx>>(&mut self, value: &T) -> T {
+        if !value.has_projection_types() {
+            value.clone()
+        } else {
+            value.fold_with(self)
+        }
+    }
+}
+
+impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> {
+    fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'gcx> {
+        self.tcx
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'gcx>) -> Ty<'gcx> {
+        if !ty.has_projection_types() {
+            ty
+        } else {
+            self.tcx.trans_trait_caches.project_cache.memoize(ty, || {
+                debug!("AssociatedTypeNormalizer: ty={:?}", ty);
+                self.tcx.normalize_associated_type(&ty)
+            })
+        }
+    }
+}
 
 /// Specializes caches used in trans -- in particular, they assume all
 /// types are fully monomorphized and that free regions can be erased.
 pub struct TransTraitCaches<'tcx> {
-    pub trait_cache: RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>,
-    pub project_cache: RefCell<DepTrackingMap<ProjectionCache<'tcx>>>,
+    trait_cache: RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>,
+    project_cache: RefCell<DepTrackingMap<ProjectionCache<'tcx>>>,
 }
 
 impl<'tcx> TransTraitCaches<'tcx> {
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index ba2b807d5a0..13bb0d37125 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -467,13 +467,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,
-                                                                 self.param_substs,
-                                                                 &target_ty);
+                let target_ty = self.scx.tcx().trans_apply_param_substs(self.param_substs,
+                                                                        &target_ty);
                 let source_ty = operand.ty(self.mir, self.scx.tcx());
-                let source_ty = monomorphize::apply_param_substs(self.scx,
-                                                                 self.param_substs,
-                                                                 &source_ty);
+                let source_ty = self.scx.tcx().trans_apply_param_substs(self.param_substs,
+                                                                        &source_ty);
                 let (source_ty, target_ty) = find_vtable_types_for_unsizing(self.scx,
                                                                             source_ty,
                                                                             target_ty);
@@ -489,10 +487,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
             }
             mir::Rvalue::Cast(mir::CastKind::ReifyFnPointer, ref operand, _) => {
                 let fn_ty = operand.ty(self.mir, self.scx.tcx());
-                let fn_ty = monomorphize::apply_param_substs(
-                    self.scx,
-                    self.param_substs,
-                    &fn_ty);
+                let fn_ty = self.scx.tcx().trans_apply_param_substs(self.param_substs,
+                                                                    &fn_ty);
                 visit_fn_use(self.scx, fn_ty, false, &mut self.output);
             }
             mir::Rvalue::Cast(mir::CastKind::ClosureFnPointer, ref operand, _) => {
@@ -534,9 +530,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
         }
 
         if let mir::Literal::Item { def_id, substs } = constant.literal {
-            let substs = monomorphize::apply_param_substs(self.scx,
-                                                          self.param_substs,
-                                                          &substs);
+            let substs = self.scx.tcx().trans_apply_param_substs(self.param_substs,
+                                                                 &substs);
             let instance = monomorphize::resolve(self.scx, def_id, substs);
             collect_neighbours(self.scx, instance, self.output);
         }
@@ -552,17 +547,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
         match *kind {
             mir::TerminatorKind::Call { ref func, .. } => {
                 let callee_ty = func.ty(self.mir, tcx);
-                let callee_ty = monomorphize::apply_param_substs(
-                    self.scx, self.param_substs, &callee_ty);
+                let callee_ty = tcx.trans_apply_param_substs(self.param_substs, &callee_ty);
                 visit_fn_use(self.scx, callee_ty, true, &mut self.output);
             }
             mir::TerminatorKind::Drop { ref location, .. } |
             mir::TerminatorKind::DropAndReplace { ref location, .. } => {
                 let ty = location.ty(self.mir, self.scx.tcx())
                     .to_ty(self.scx.tcx());
-                let ty = monomorphize::apply_param_substs(self.scx,
-                                                          self.param_substs,
-                                                          &ty);
+                let ty = tcx.trans_apply_param_substs(self.param_substs, &ty);
                 visit_drop_use(self.scx, ty, true, self.output);
             }
             mir::TerminatorKind::Goto { .. } |
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index 5d58c935389..648ea92c843 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -564,7 +564,7 @@ pub fn def_ty<'a, 'tcx>(shared: &SharedCrateContext<'a, 'tcx>,
                         -> Ty<'tcx>
 {
     let ty = shared.tcx().item_type(def_id);
-    monomorphize::apply_param_substs(shared, substs, &ty)
+    shared.tcx().trans_apply_param_substs(substs, &ty)
 }
 
 /// Return the substituted type of an instance.
@@ -573,5 +573,5 @@ pub fn instance_ty<'a, 'tcx>(shared: &SharedCrateContext<'a, 'tcx>,
                              -> Ty<'tcx>
 {
     let ty = instance.def.def_ty(shared.tcx());
-    monomorphize::apply_param_substs(shared, instance.substs, &ty)
+    shared.tcx().trans_apply_param_substs(instance.substs, &ty)
 }
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index 8bce0cf85c0..dbae79e034d 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -260,9 +260,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
     fn monomorphize<T>(&self, value: &T) -> T
         where T: TransNormalize<'tcx>
     {
-        monomorphize::apply_param_substs(self.ccx.shared(),
-                                         self.substs,
-                                         value)
+        self.ccx.tcx().trans_apply_param_substs(self.substs, value)
     }
 
     fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs
index 3d8c5085462..2669f722f9c 100644
--- a/src/librustc_trans/mir/mod.rs
+++ b/src/librustc_trans/mir/mod.rs
@@ -22,7 +22,7 @@ use base;
 use builder::Builder;
 use common::{self, CrateContext, Funclet};
 use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext};
-use monomorphize::{self, Instance};
+use monomorphize::Instance;
 use abi::FnType;
 use type_of;
 
@@ -102,8 +102,9 @@ pub struct MirContext<'a, 'tcx:'a> {
 
 impl<'a, 'tcx> MirContext<'a, 'tcx> {
     pub fn monomorphize<T>(&self, value: &T) -> T
-        where T: TransNormalize<'tcx> {
-        monomorphize::apply_param_substs(self.ccx.shared(), self.param_substs, value)
+        where T: TransNormalize<'tcx>
+    {
+        self.ccx.tcx().trans_apply_param_substs(self.param_substs, value)
     }
 
     pub fn set_debug_loc(&mut self, bcx: &Builder, source_info: mir::SourceInfo) {
diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs
index 33626e7c39f..d27eeb2b646 100644
--- a/src/librustc_trans/monomorphize.rs
+++ b/src/librustc_trans/monomorphize.rs
@@ -13,17 +13,13 @@ use common::*;
 use glue;
 
 use rustc::hir::def_id::DefId;
-use rustc::infer::TransNormalize;
 use rustc::middle::lang_items::DropInPlaceFnLangItem;
-use rustc::traits::{self, SelectionContext, Reveal};
+use rustc::traits;
 use rustc::ty::adjustment::CustomCoerceUnsized;
-use rustc::ty::fold::{TypeFolder, TypeFoldable};
 use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::util::common::MemoizationMap;
 
-use syntax::ast;
-use syntax::codemap::{Span, DUMMY_SP};
+use syntax::codemap::DUMMY_SP;
 
 pub use rustc::ty::Instance;
 
@@ -104,73 +100,6 @@ pub fn resolve_closure<'a, 'tcx> (
     }
 }
 
-/// Attempts to resolve an obligation. The result is a shallow vtable resolution -- meaning that we
-/// do not (necessarily) resolve all nested obligations on the impl. Note that type check should
-/// guarantee to us that all nested obligations *could be* resolved if we wanted to.
-fn fulfill_obligation<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
-                                span: Span,
-                                trait_ref: ty::PolyTraitRef<'tcx>)
-                                -> traits::Vtable<'tcx, ()>
-{
-    let tcx = scx.tcx();
-
-    // Remove any references to regions; this helps improve caching.
-    let trait_ref = tcx.erase_regions(&trait_ref);
-
-    tcx.trans_trait_caches.trait_cache.memoize(trait_ref, || {
-        debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
-               trait_ref, trait_ref.def_id());
-
-        // Do the initial selection for the obligation. This yields the
-        // shallow result we are looking for -- that is, what specific impl.
-        tcx.infer_ctxt((), Reveal::All).enter(|infcx| {
-            let mut selcx = SelectionContext::new(&infcx);
-
-            let obligation_cause = traits::ObligationCause::misc(span,
-                                                             ast::DUMMY_NODE_ID);
-            let obligation = traits::Obligation::new(obligation_cause,
-                                                     trait_ref.to_poly_trait_predicate());
-
-            let selection = match selcx.select(&obligation) {
-                Ok(Some(selection)) => selection,
-                Ok(None) => {
-                    // Ambiguity can happen when monomorphizing during trans
-                    // expands to some humongo type that never occurred
-                    // statically -- this humongo type can then overflow,
-                    // leading to an ambiguous result. So report this as an
-                    // overflow bug, since I believe this is the only case
-                    // where ambiguity can result.
-                    debug!("Encountered ambiguity selecting `{:?}` during trans, \
-                            presuming due to overflow",
-                           trait_ref);
-                    tcx.sess.span_fatal(span,
-                        "reached the recursion limit during monomorphization \
-                         (selection ambiguity)");
-                }
-                Err(e) => {
-                    span_bug!(span, "Encountered error `{:?}` selecting `{:?}` during trans",
-                              e, trait_ref)
-                }
-            };
-
-            debug!("fulfill_obligation: selection={:?}", selection);
-
-            // Currently, we use a fulfillment context to completely resolve
-            // all nested obligations. This is because they can inform the
-            // inference of the impl's type parameters.
-            let mut fulfill_cx = traits::FulfillmentContext::new();
-            let vtable = selection.map(|predicate| {
-                debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate);
-                fulfill_cx.register_predicate_obligation(&infcx, predicate);
-            });
-            let vtable = infcx.drain_fulfillment_cx_or_panic(span, &mut fulfill_cx, &vtable);
-
-            info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
-            vtable
-        })
-    })
-}
-
 fn resolve_associated_item<'a, 'tcx>(
     scx: &SharedCrateContext<'a, 'tcx>,
     trait_item: &ty::AssociatedItem,
@@ -185,7 +114,7 @@ fn resolve_associated_item<'a, 'tcx>(
            def_id, trait_id, rcvr_substs);
 
     let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
-    let vtbl = fulfill_obligation(scx, DUMMY_SP, ty::Binder(trait_ref));
+    let vtbl = tcx.trans_fulfill_obligation(DUMMY_SP, ty::Binder(trait_ref));
 
     // Now that we know which impl is being used, we can dispatch to
     // the actual function:
@@ -285,7 +214,7 @@ pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, 'tcx
         substs: scx.tcx().mk_substs_trait(source_ty, &[target_ty])
     });
 
-    match fulfill_obligation(scx, DUMMY_SP, trait_ref) {
+    match scx.tcx().trans_fulfill_obligation(DUMMY_SP, trait_ref) {
         traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
             scx.tcx().coerce_unsized_info(impl_def_id).custom_kind.unwrap()
         }
@@ -295,21 +224,6 @@ pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, '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>(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);
-    let substituted = scx.tcx().erase_regions(&substituted);
-    AssociatedTypeNormalizer::new(tcx).fold(&substituted)
-}
-
 /// Returns the normalized type of a struct field
 pub fn field_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           param_substs: &Substs<'tcx>,
@@ -319,37 +233,3 @@ pub fn field_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     tcx.normalize_associated_type(&f.ty(tcx, param_substs))
 }
 
-struct AssociatedTypeNormalizer<'a, 'gcx: 'a> {
-    tcx: TyCtxt<'a, 'gcx, 'gcx>,
-}
-
-impl<'a, 'gcx> AssociatedTypeNormalizer<'a, 'gcx> {
-    fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) -> Self {
-        AssociatedTypeNormalizer { tcx }
-    }
-
-    fn fold<T:TypeFoldable<'gcx>>(&mut self, value: &T) -> T {
-        if !value.has_projection_types() {
-            value.clone()
-        } else {
-            value.fold_with(self)
-        }
-    }
-}
-
-impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> {
-    fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'gcx> {
-        self.tcx
-    }
-
-    fn fold_ty(&mut self, ty: Ty<'gcx>) -> Ty<'gcx> {
-        if !ty.has_projection_types() {
-            ty
-        } else {
-            self.tcx.trans_trait_caches.project_cache.memoize(ty, || {
-                debug!("AssociatedTypeNormalizer: ty={:?}", ty);
-                self.tcx.normalize_associated_type(&ty)
-            })
-        }
-    }
-}