@@ -20,6 +20,7 @@ use rustc::cfg;
2020use rustc:: hir:: def:: Def ;
2121use rustc:: hir:: def_id:: DefId ;
2222use rustc:: infer;
23+ use rustc:: util:: common:: MemoizationMap ;
2324use middle:: lang_items:: LangItem ;
2425use rustc:: ty:: subst:: Substs ;
2526use abi:: { Abi , FnType } ;
@@ -54,7 +55,7 @@ use syntax::codemap::{DUMMY_SP, Span};
5455use syntax:: parse:: token:: InternedString ;
5556use syntax:: parse:: token;
5657
57- pub use context:: CrateContext ;
58+ pub use context:: { CrateContext , SharedCrateContext } ;
5859
5960/// Is the type's representation size known at compile time?
6061pub 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) ->
10511052/// Attempts to resolve an obligation. The result is a shallow vtable resolution -- meaning that we
10521053/// do not (necessarily) resolve all nested obligations on the impl. Note that type check should
10531054/// 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 > ,
10551056 span : Span ,
10561057 trait_ref : ty:: PolyTraitRef < ' tcx > )
10571058 -> traits:: Vtable < ' tcx , ( ) >
@@ -1061,68 +1062,63 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
10611062 // Remove any references to regions; this helps improve caching.
10621063 let trait_ref = tcx. erase_regions ( & trait_ref) ;
10631064
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+ } ;
11201106
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+ ) ;
11221117
1123- ccx . trait_cache ( ) . borrow_mut ( ) . insert ( trait_ref, vtable. clone ( ) ) ;
1118+ info ! ( "Cache miss: {:?} => {:?}" , trait_ref, vtable) ;
11241119
1125- vtable
1120+ vtable
1121+ } )
11261122}
11271123
11281124/// Normalizes the predicates and checks whether they hold. If this
0 commit comments