@@ -28,6 +28,7 @@ use infer::{self, InferOk, TypeOrigin};
2828use ty:: subst:: Subst ;
2929use ty:: { self , ToPredicate , ToPolyTraitRef , Ty , TyCtxt } ;
3030use ty:: fold:: { TypeFoldable , TypeFolder } ;
31+ use rustc_data_structures:: snapshot_map:: { Snapshot , SnapshotMap } ;
3132use syntax:: parse:: token;
3233use syntax:: ast;
3334use util:: common:: FN_OUTPUT_NAME ;
@@ -424,19 +425,25 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
424425
425426 let obligation = Obligation :: with_depth ( cause. clone ( ) , depth, projection_ty. clone ( ) ) ;
426427 match project_type ( selcx, & obligation) {
427- Ok ( ProjectedTy :: Progress ( projected_ty, mut obligations) ) => {
428+ Ok ( ProjectedTy :: Progress ( Progress { ty : projected_ty,
429+ mut obligations,
430+ cacheable } ) ) => {
428431 // if projection succeeded, then what we get out of this
429432 // is also non-normalized (consider: it was derived from
430433 // an impl, where-clause etc) and hence we must
431434 // re-normalize it
432435
433436 debug ! ( "opt_normalize_projection_type: \
434- projected_ty={:?} depth={} obligations={:?}",
437+ projected_ty={:?} \
438+ depth={} \
439+ obligations={:?} \
440+ cacheable={:?}",
435441 projected_ty,
436442 depth,
437- obligations) ;
443+ obligations,
444+ cacheable) ;
438445
439- if projected_ty. has_projection_types ( ) {
446+ let result = if projected_ty. has_projection_types ( ) {
440447 let mut normalizer = AssociatedTypeNormalizer :: new ( selcx, cause, depth+1 ) ;
441448 let normalized_ty = normalizer. fold ( & projected_ty) ;
442449
@@ -455,7 +462,9 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
455462 value : projected_ty,
456463 obligations : obligations,
457464 } )
458- }
465+ } ;
466+
467+ result
459468 }
460469 Ok ( ProjectedTy :: NoProgress ( projected_ty) ) => {
461470 debug ! ( "opt_normalize_projection_type: \
@@ -520,11 +529,37 @@ fn normalize_to_error<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tc
520529}
521530
522531enum ProjectedTy < ' tcx > {
523- Progress ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > ) ,
532+ Progress ( Progress < ' tcx > ) ,
524533 NoProgress ( Ty < ' tcx > ) ,
525534}
526535
536+ struct Progress < ' tcx > {
537+ ty : Ty < ' tcx > ,
538+ obligations : Vec < PredicateObligation < ' tcx > > ,
539+ cacheable : bool ,
540+ }
541+
542+ impl < ' tcx > Progress < ' tcx > {
543+ fn error < ' a , ' gcx > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ) -> Self {
544+ Progress {
545+ ty : tcx. types . err ,
546+ obligations : vec ! [ ] ,
547+ cacheable : true
548+ }
549+ }
550+
551+ fn with_addl_obligations ( mut self ,
552+ mut obligations : Vec < PredicateObligation < ' tcx > > )
553+ -> Self {
554+ self . obligations . append ( & mut obligations) ;
555+ self
556+ }
557+ }
558+
527559/// Compute the result of a projection type (if we can).
560+ ///
561+ /// IMPORTANT:
562+ /// - `obligation` must be fully normalized
528563fn project_type < ' cx , ' gcx , ' tcx > (
529564 selcx : & mut SelectionContext < ' cx , ' gcx , ' tcx > ,
530565 obligation : & ProjectionTyObligation < ' tcx > )
@@ -539,13 +574,12 @@ fn project_type<'cx, 'gcx, 'tcx>(
539574 selcx. infcx ( ) . report_overflow_error ( & obligation, true ) ;
540575 }
541576
542- let obligation_trait_ref =
543- selcx. infcx ( ) . resolve_type_vars_if_possible ( & obligation. predicate . trait_ref ) ;
577+ let obligation_trait_ref = & obligation. predicate . trait_ref ;
544578
545579 debug ! ( "project: obligation_trait_ref={:?}" , obligation_trait_ref) ;
546580
547581 if obligation_trait_ref. references_error ( ) {
548- return Ok ( ProjectedTy :: Progress ( selcx. tcx ( ) . types . err , vec ! ( ) ) ) ;
582+ return Ok ( ProjectedTy :: Progress ( Progress :: error ( selcx. tcx ( ) ) ) ) ;
549583 }
550584
551585 let mut candidates = ProjectionTyCandidateSet {
@@ -623,16 +657,17 @@ fn project_type<'cx, 'gcx, 'tcx>(
623657
624658 match candidates. vec . pop ( ) {
625659 Some ( candidate) => {
626- let ( ty , obligations ) = confirm_candidate ( selcx ,
627- obligation ,
628- & obligation_trait_ref ,
629- candidate ) ;
630- Ok ( ProjectedTy :: Progress ( ty , obligations ) )
660+ Ok ( ProjectedTy :: Progress (
661+ confirm_candidate ( selcx ,
662+ obligation ,
663+ & obligation_trait_ref ,
664+ candidate ) ) )
631665 }
632666 None => {
633- Ok ( ProjectedTy :: NoProgress ( selcx. tcx ( ) . mk_projection (
634- obligation. predicate . trait_ref . clone ( ) ,
635- obligation. predicate . item_name ) ) )
667+ Ok ( ProjectedTy :: NoProgress (
668+ selcx. tcx ( ) . mk_projection (
669+ obligation. predicate . trait_ref . clone ( ) ,
670+ obligation. predicate . item_name ) ) )
636671 }
637672 }
638673}
@@ -935,7 +970,7 @@ fn confirm_candidate<'cx, 'gcx, 'tcx>(
935970 obligation : & ProjectionTyObligation < ' tcx > ,
936971 obligation_trait_ref : & ty:: TraitRef < ' tcx > ,
937972 candidate : ProjectionTyCandidate < ' tcx > )
938- -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
973+ -> Progress < ' tcx >
939974{
940975 debug ! ( "confirm_candidate(candidate={:?}, obligation={:?})" ,
941976 candidate,
@@ -957,7 +992,7 @@ fn confirm_select_candidate<'cx, 'gcx, 'tcx>(
957992 selcx : & mut SelectionContext < ' cx , ' gcx , ' tcx > ,
958993 obligation : & ProjectionTyObligation < ' tcx > ,
959994 obligation_trait_ref : & ty:: TraitRef < ' tcx > )
960- -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
995+ -> Progress < ' tcx >
961996{
962997 let poly_trait_ref = obligation_trait_ref. to_poly_trait_ref ( ) ;
963998 let trait_obligation = obligation. with ( poly_trait_ref. to_poly_trait_predicate ( ) ) ;
@@ -995,7 +1030,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
9951030 selcx : & mut SelectionContext < ' cx , ' gcx , ' tcx > ,
9961031 obligation : & ProjectionTyObligation < ' tcx > ,
9971032 obligation_trait_ref : & ty:: TraitRef < ' tcx > )
998- -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
1033+ -> Progress < ' tcx >
9991034{
10001035 let self_ty = obligation_trait_ref. self_ty ( ) ;
10011036 let object_ty = selcx. infcx ( ) . shallow_resolve ( self_ty) ;
@@ -1007,7 +1042,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
10071042 span_bug ! (
10081043 obligation. cause. span,
10091044 "confirm_object_candidate called with non-object: {:?}" ,
1010- object_ty) ;
1045+ object_ty)
10111046 }
10121047 } ;
10131048 let projection_bounds = data. projection_bounds_with_self_ty ( selcx. tcx ( ) , object_ty) ;
@@ -1051,7 +1086,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
10511086 debug ! ( "confirm_object_candidate: no env-predicate \
10521087 found in object type `{:?}`; ill-formed",
10531088 object_ty) ;
1054- return ( selcx. tcx ( ) . types . err , vec ! ( ) ) ;
1089+ return Progress :: error ( selcx. tcx ( ) ) ;
10551090 }
10561091 }
10571092 } ;
@@ -1063,7 +1098,7 @@ fn confirm_fn_pointer_candidate<'cx, 'gcx, 'tcx>(
10631098 selcx : & mut SelectionContext < ' cx , ' gcx , ' tcx > ,
10641099 obligation : & ProjectionTyObligation < ' tcx > ,
10651100 fn_pointer_vtable : VtableFnPointerData < ' tcx , PredicateObligation < ' tcx > > )
1066- -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
1101+ -> Progress < ' tcx >
10671102{
10681103 // FIXME(#32730) drop this assertion once obligations are propagated from inference (fn pointer
10691104 // vtable nested obligations ONLY come from unification in inference)
@@ -1077,31 +1112,30 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>(
10771112 selcx : & mut SelectionContext < ' cx , ' gcx , ' tcx > ,
10781113 obligation : & ProjectionTyObligation < ' tcx > ,
10791114 vtable : VtableClosureData < ' tcx , PredicateObligation < ' tcx > > )
1080- -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
1115+ -> Progress < ' tcx >
10811116{
10821117 let closure_typer = selcx. closure_typer ( ) ;
10831118 let closure_type = closure_typer. closure_type ( vtable. closure_def_id , vtable. substs ) ;
10841119 let Normalized {
10851120 value : closure_type,
1086- mut obligations
1121+ obligations
10871122 } = normalize_with_depth ( selcx,
10881123 obligation. cause . clone ( ) ,
10891124 obligation. recursion_depth +1 ,
10901125 & closure_type) ;
1091- let ( ty, mut cc_obligations) = confirm_callable_candidate ( selcx,
1092- obligation,
1093- & closure_type. sig ,
1094- util:: TupleArgumentsFlag :: No ) ;
1095- obligations. append ( & mut cc_obligations) ;
1096- ( ty, obligations)
1126+ confirm_callable_candidate ( selcx,
1127+ obligation,
1128+ & closure_type. sig ,
1129+ util:: TupleArgumentsFlag :: No )
1130+ . with_addl_obligations ( obligations)
10971131}
10981132
10991133fn confirm_callable_candidate < ' cx , ' gcx , ' tcx > (
11001134 selcx : & mut SelectionContext < ' cx , ' gcx , ' tcx > ,
11011135 obligation : & ProjectionTyObligation < ' tcx > ,
11021136 fn_sig : & ty:: PolyFnSig < ' tcx > ,
11031137 flag : util:: TupleArgumentsFlag )
1104- -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
1138+ -> Progress < ' tcx >
11051139{
11061140 let tcx = selcx. tcx ( ) ;
11071141
@@ -1134,47 +1168,38 @@ fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>(
11341168 selcx : & mut SelectionContext < ' cx , ' gcx , ' tcx > ,
11351169 obligation : & ProjectionTyObligation < ' tcx > ,
11361170 poly_projection : ty:: PolyProjectionPredicate < ' tcx > )
1137- -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
1171+ -> Progress < ' tcx >
11381172{
11391173 let infcx = selcx. infcx ( ) ;
1140-
1141- let projection =
1142- infcx. replace_late_bound_regions_with_fresh_var (
1143- obligation. cause . span ,
1144- infer:: LateBoundRegionConversionTime :: HigherRankedType ,
1145- & poly_projection) . 0 ;
1146-
1147- assert_eq ! ( projection. projection_ty. item_name,
1148- obligation. predicate. item_name) ;
1149-
11501174 let origin = TypeOrigin :: RelateOutputImplTypes ( obligation. cause . span ) ;
1151- let obligations = match infcx. eq_trait_refs ( false ,
1152- origin,
1153- obligation. predicate . trait_ref . clone ( ) ,
1154- projection. projection_ty . trait_ref . clone ( ) ) {
1155- Ok ( InferOk { obligations, .. } ) => {
1156- // FIXME(#32730) once obligations are generated in inference, remove this assertion
1175+ let trait_ref = obligation. predicate . trait_ref ;
1176+ match infcx. match_poly_projection_predicate ( origin, poly_projection, trait_ref) {
1177+ Ok ( InferOk { value : ty_match, obligations } ) => {
1178+ // FIXME(#32730) once obligations are generated in inference, drop this assertion
11571179 assert ! ( obligations. is_empty( ) ) ;
1158- obligations
1180+ Progress {
1181+ ty : ty_match. value ,
1182+ obligations : obligations,
1183+ cacheable : ty_match. unconstrained_regions . is_empty ( ) ,
1184+ }
11591185 }
11601186 Err ( e) => {
11611187 span_bug ! (
11621188 obligation. cause. span,
1163- "Failed to unify `{:?}` and `{:?}` in projection: {}" ,
1189+ "Failed to unify obligation `{:?}` \
1190+ with poly_projection `{:?}`: {:?}",
11641191 obligation,
1165- projection ,
1192+ poly_projection ,
11661193 e) ;
11671194 }
1168- } ;
1169-
1170- ( projection. ty , obligations)
1195+ }
11711196}
11721197
11731198fn confirm_impl_candidate < ' cx , ' gcx , ' tcx > (
11741199 selcx : & mut SelectionContext < ' cx , ' gcx , ' tcx > ,
11751200 obligation : & ProjectionTyObligation < ' tcx > ,
11761201 impl_vtable : VtableImplData < ' tcx , PredicateObligation < ' tcx > > )
1177- -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
1202+ -> Progress < ' tcx >
11781203{
11791204 let VtableImplData { substs, nested, impl_def_id } = impl_vtable;
11801205
@@ -1195,7 +1220,11 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
11951220 tcx. types . err
11961221 } ) ;
11971222 let substs = translate_substs ( selcx. infcx ( ) , impl_def_id, substs, node_item. node ) ;
1198- ( ty. subst ( tcx, substs) , nested)
1223+ Progress {
1224+ ty : ty. subst ( tcx, substs) ,
1225+ obligations : nested,
1226+ cacheable : true
1227+ }
11991228 }
12001229 None => {
12011230 span_bug ! ( obligation. cause. span,
0 commit comments