@@ -20,6 +20,7 @@ use rustc::cfg;
20
20
use rustc:: hir:: def:: Def ;
21
21
use rustc:: hir:: def_id:: DefId ;
22
22
use rustc:: infer;
23
+ use rustc:: util:: common:: MemoizationMap ;
23
24
use middle:: lang_items:: LangItem ;
24
25
use rustc:: ty:: subst:: Substs ;
25
26
use abi:: { Abi , FnType } ;
@@ -54,7 +55,7 @@ use syntax::codemap::{DUMMY_SP, Span};
54
55
use syntax:: parse:: token:: InternedString ;
55
56
use syntax:: parse:: token;
56
57
57
- pub use context:: CrateContext ;
58
+ pub use context:: { CrateContext , SharedCrateContext } ;
58
59
59
60
/// Is the type's representation size known at compile time?
60
61
pub fn type_is_sized < ' tcx > ( tcx : & TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> bool {
@@ -1051,7 +1052,7 @@ pub fn expr_ty_adjusted<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &hir::Expr) ->
1051
1052
/// Attempts to resolve an obligation. The result is a shallow vtable resolution -- meaning that we
1052
1053
/// do not (necessarily) resolve all nested obligations on the impl. Note that type check should
1053
1054
/// guarantee to us that all nested obligations *could be* resolved if we wanted to.
1054
- pub fn fulfill_obligation < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
1055
+ pub fn fulfill_obligation < ' a , ' tcx > ( ccx : & SharedCrateContext < ' a , ' tcx > ,
1055
1056
span : Span ,
1056
1057
trait_ref : ty:: PolyTraitRef < ' tcx > )
1057
1058
-> traits:: Vtable < ' tcx , ( ) >
@@ -1061,68 +1062,63 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
1061
1062
// Remove any references to regions; this helps improve caching.
1062
1063
let trait_ref = tcx. erase_regions ( & trait_ref) ;
1063
1064
1064
- // First check the cache.
1065
- match ccx. trait_cache ( ) . borrow ( ) . get ( & trait_ref) {
1066
- Some ( vtable) => {
1067
- info ! ( "Cache hit: {:?}" , trait_ref) ;
1068
- return ( * vtable) . clone ( ) ;
1069
- }
1070
- None => { }
1071
- }
1072
-
1073
- debug ! ( "trans fulfill_obligation: trait_ref={:?} def_id={:?}" ,
1074
- trait_ref, trait_ref. def_id( ) ) ;
1075
-
1076
-
1077
- // Do the initial selection for the obligation. This yields the
1078
- // shallow result we are looking for -- that is, what specific impl.
1079
- let infcx = infer:: normalizing_infer_ctxt ( tcx, & tcx. tables , ProjectionMode :: Any ) ;
1080
- let mut selcx = SelectionContext :: new ( & infcx) ;
1081
-
1082
- let obligation =
1083
- traits:: Obligation :: new ( traits:: ObligationCause :: misc ( span, ast:: DUMMY_NODE_ID ) ,
1084
- trait_ref. to_poly_trait_predicate ( ) ) ;
1085
- let selection = match selcx. select ( & obligation) {
1086
- Ok ( Some ( selection) ) => selection,
1087
- Ok ( None ) => {
1088
- // Ambiguity can happen when monomorphizing during trans
1089
- // expands to some humongo type that never occurred
1090
- // statically -- this humongo type can then overflow,
1091
- // leading to an ambiguous result. So report this as an
1092
- // overflow bug, since I believe this is the only case
1093
- // where ambiguity can result.
1094
- debug ! ( "Encountered ambiguity selecting `{:?}` during trans, \
1095
- presuming due to overflow",
1096
- trait_ref) ;
1097
- ccx. sess ( ) . span_fatal (
1098
- span,
1099
- "reached the recursion limit during monomorphization (selection ambiguity)" ) ;
1100
- }
1101
- Err ( e) => {
1102
- span_bug ! (
1103
- span,
1104
- "Encountered error `{:?}` selecting `{:?}` during trans" ,
1105
- e,
1106
- trait_ref)
1107
- }
1108
- } ;
1109
-
1110
- // Currently, we use a fulfillment context to completely resolve
1111
- // all nested obligations. This is because they can inform the
1112
- // inference of the impl's type parameters.
1113
- let mut fulfill_cx = traits:: FulfillmentContext :: new ( ) ;
1114
- let vtable = selection. map ( |predicate| {
1115
- fulfill_cx. register_predicate_obligation ( & infcx, predicate) ;
1116
- } ) ;
1117
- let vtable = infer:: drain_fulfillment_cx_or_panic (
1118
- span, & infcx, & mut fulfill_cx, & vtable
1119
- ) ;
1065
+ ccx. trait_cache ( ) . memoize ( trait_ref, || {
1066
+ debug ! ( "trans fulfill_obligation: trait_ref={:?} def_id={:?}" ,
1067
+ trait_ref, trait_ref. def_id( ) ) ;
1068
+
1069
+ // Do the initial selection for the obligation. This yields the
1070
+ // shallow result we are looking for -- that is, what specific impl.
1071
+ let infcx = infer:: normalizing_infer_ctxt ( tcx,
1072
+ & tcx. tables ,
1073
+ ProjectionMode :: Any ) ;
1074
+ let mut selcx = SelectionContext :: new ( & infcx) ;
1075
+
1076
+ let obligation_cause = traits:: ObligationCause :: misc ( span,
1077
+ ast:: DUMMY_NODE_ID ) ;
1078
+ let obligation = traits:: Obligation :: new ( obligation_cause,
1079
+ trait_ref. to_poly_trait_predicate ( ) ) ;
1080
+
1081
+ let selection = match selcx. select ( & obligation) {
1082
+ Ok ( Some ( selection) ) => selection,
1083
+ Ok ( None ) => {
1084
+ // Ambiguity can happen when monomorphizing during trans
1085
+ // expands to some humongo type that never occurred
1086
+ // statically -- this humongo type can then overflow,
1087
+ // leading to an ambiguous result. So report this as an
1088
+ // overflow bug, since I believe this is the only case
1089
+ // where ambiguity can result.
1090
+ debug ! ( "Encountered ambiguity selecting `{:?}` during trans, \
1091
+ presuming due to overflow",
1092
+ trait_ref) ;
1093
+ ccx. sess ( ) . span_fatal (
1094
+ span,
1095
+ "reached the recursion limit during monomorphization \
1096
+ (selection ambiguity)") ;
1097
+ }
1098
+ Err ( e) => {
1099
+ span_bug ! (
1100
+ span,
1101
+ "Encountered error `{:?}` selecting `{:?}` during trans" ,
1102
+ e,
1103
+ trait_ref)
1104
+ }
1105
+ } ;
1120
1106
1121
- info ! ( "Cache miss: {:?} => {:?}" , trait_ref, vtable) ;
1107
+ // Currently, we use a fulfillment context to completely resolve
1108
+ // all nested obligations. This is because they can inform the
1109
+ // inference of the impl's type parameters.
1110
+ let mut fulfill_cx = traits:: FulfillmentContext :: new ( ) ;
1111
+ let vtable = selection. map ( |predicate| {
1112
+ fulfill_cx. register_predicate_obligation ( & infcx, predicate) ;
1113
+ } ) ;
1114
+ let vtable = infer:: drain_fulfillment_cx_or_panic (
1115
+ span, & infcx, & mut fulfill_cx, & vtable
1116
+ ) ;
1122
1117
1123
- ccx . trait_cache ( ) . borrow_mut ( ) . insert ( trait_ref, vtable. clone ( ) ) ;
1118
+ info ! ( "Cache miss: {:?} => {:?}" , trait_ref, vtable) ;
1124
1119
1125
- vtable
1120
+ vtable
1121
+ } )
1126
1122
}
1127
1123
1128
1124
/// Normalizes the predicates and checks whether they hold. If this
0 commit comments