@@ -28,6 +28,7 @@ use infer::{self, InferOk, TypeOrigin};
28
28
use ty:: subst:: Subst ;
29
29
use ty:: { self , ToPredicate , ToPolyTraitRef , Ty , TyCtxt } ;
30
30
use ty:: fold:: { TypeFoldable , TypeFolder } ;
31
+ use rustc_data_structures:: snapshot_map:: { Snapshot , SnapshotMap } ;
31
32
use syntax:: parse:: token;
32
33
use syntax:: ast;
33
34
use util:: common:: FN_OUTPUT_NAME ;
@@ -424,19 +425,25 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
424
425
425
426
let obligation = Obligation :: with_depth ( cause. clone ( ) , depth, projection_ty. clone ( ) ) ;
426
427
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 } ) ) => {
428
431
// if projection succeeded, then what we get out of this
429
432
// is also non-normalized (consider: it was derived from
430
433
// an impl, where-clause etc) and hence we must
431
434
// re-normalize it
432
435
433
436
debug ! ( "opt_normalize_projection_type: \
434
- projected_ty={:?} depth={} obligations={:?}",
437
+ projected_ty={:?} \
438
+ depth={} \
439
+ obligations={:?} \
440
+ cacheable={:?}",
435
441
projected_ty,
436
442
depth,
437
- obligations) ;
443
+ obligations,
444
+ cacheable) ;
438
445
439
- if projected_ty. has_projection_types ( ) {
446
+ let result = if projected_ty. has_projection_types ( ) {
440
447
let mut normalizer = AssociatedTypeNormalizer :: new ( selcx, cause, depth+1 ) ;
441
448
let normalized_ty = normalizer. fold ( & projected_ty) ;
442
449
@@ -455,7 +462,9 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
455
462
value : projected_ty,
456
463
obligations : obligations,
457
464
} )
458
- }
465
+ } ;
466
+
467
+ result
459
468
}
460
469
Ok ( ProjectedTy :: NoProgress ( projected_ty) ) => {
461
470
debug ! ( "opt_normalize_projection_type: \
@@ -520,11 +529,37 @@ fn normalize_to_error<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tc
520
529
}
521
530
522
531
enum ProjectedTy < ' tcx > {
523
- Progress ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > ) ,
532
+ Progress ( Progress < ' tcx > ) ,
524
533
NoProgress ( Ty < ' tcx > ) ,
525
534
}
526
535
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
+
527
559
/// Compute the result of a projection type (if we can).
560
+ ///
561
+ /// IMPORTANT:
562
+ /// - `obligation` must be fully normalized
528
563
fn project_type < ' cx , ' gcx , ' tcx > (
529
564
selcx : & mut SelectionContext < ' cx , ' gcx , ' tcx > ,
530
565
obligation : & ProjectionTyObligation < ' tcx > )
@@ -539,13 +574,12 @@ fn project_type<'cx, 'gcx, 'tcx>(
539
574
selcx. infcx ( ) . report_overflow_error ( & obligation, true ) ;
540
575
}
541
576
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 ;
544
578
545
579
debug ! ( "project: obligation_trait_ref={:?}" , obligation_trait_ref) ;
546
580
547
581
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 ( ) ) ) ) ;
549
583
}
550
584
551
585
let mut candidates = ProjectionTyCandidateSet {
@@ -623,16 +657,17 @@ fn project_type<'cx, 'gcx, 'tcx>(
623
657
624
658
match candidates. vec . pop ( ) {
625
659
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 ) ) )
631
665
}
632
666
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 ) ) )
636
671
}
637
672
}
638
673
}
@@ -935,7 +970,7 @@ fn confirm_candidate<'cx, 'gcx, 'tcx>(
935
970
obligation : & ProjectionTyObligation < ' tcx > ,
936
971
obligation_trait_ref : & ty:: TraitRef < ' tcx > ,
937
972
candidate : ProjectionTyCandidate < ' tcx > )
938
- -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
973
+ -> Progress < ' tcx >
939
974
{
940
975
debug ! ( "confirm_candidate(candidate={:?}, obligation={:?})" ,
941
976
candidate,
@@ -957,7 +992,7 @@ fn confirm_select_candidate<'cx, 'gcx, 'tcx>(
957
992
selcx : & mut SelectionContext < ' cx , ' gcx , ' tcx > ,
958
993
obligation : & ProjectionTyObligation < ' tcx > ,
959
994
obligation_trait_ref : & ty:: TraitRef < ' tcx > )
960
- -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
995
+ -> Progress < ' tcx >
961
996
{
962
997
let poly_trait_ref = obligation_trait_ref. to_poly_trait_ref ( ) ;
963
998
let trait_obligation = obligation. with ( poly_trait_ref. to_poly_trait_predicate ( ) ) ;
@@ -995,7 +1030,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
995
1030
selcx : & mut SelectionContext < ' cx , ' gcx , ' tcx > ,
996
1031
obligation : & ProjectionTyObligation < ' tcx > ,
997
1032
obligation_trait_ref : & ty:: TraitRef < ' tcx > )
998
- -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
1033
+ -> Progress < ' tcx >
999
1034
{
1000
1035
let self_ty = obligation_trait_ref. self_ty ( ) ;
1001
1036
let object_ty = selcx. infcx ( ) . shallow_resolve ( self_ty) ;
@@ -1007,7 +1042,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
1007
1042
span_bug ! (
1008
1043
obligation. cause. span,
1009
1044
"confirm_object_candidate called with non-object: {:?}" ,
1010
- object_ty) ;
1045
+ object_ty)
1011
1046
}
1012
1047
} ;
1013
1048
let projection_bounds = data. projection_bounds_with_self_ty ( selcx. tcx ( ) , object_ty) ;
@@ -1051,7 +1086,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
1051
1086
debug ! ( "confirm_object_candidate: no env-predicate \
1052
1087
found in object type `{:?}`; ill-formed",
1053
1088
object_ty) ;
1054
- return ( selcx. tcx ( ) . types . err , vec ! ( ) ) ;
1089
+ return Progress :: error ( selcx. tcx ( ) ) ;
1055
1090
}
1056
1091
}
1057
1092
} ;
@@ -1063,7 +1098,7 @@ fn confirm_fn_pointer_candidate<'cx, 'gcx, 'tcx>(
1063
1098
selcx : & mut SelectionContext < ' cx , ' gcx , ' tcx > ,
1064
1099
obligation : & ProjectionTyObligation < ' tcx > ,
1065
1100
fn_pointer_vtable : VtableFnPointerData < ' tcx , PredicateObligation < ' tcx > > )
1066
- -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
1101
+ -> Progress < ' tcx >
1067
1102
{
1068
1103
// FIXME(#32730) drop this assertion once obligations are propagated from inference (fn pointer
1069
1104
// vtable nested obligations ONLY come from unification in inference)
@@ -1077,31 +1112,30 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>(
1077
1112
selcx : & mut SelectionContext < ' cx , ' gcx , ' tcx > ,
1078
1113
obligation : & ProjectionTyObligation < ' tcx > ,
1079
1114
vtable : VtableClosureData < ' tcx , PredicateObligation < ' tcx > > )
1080
- -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
1115
+ -> Progress < ' tcx >
1081
1116
{
1082
1117
let closure_typer = selcx. closure_typer ( ) ;
1083
1118
let closure_type = closure_typer. closure_type ( vtable. closure_def_id , vtable. substs ) ;
1084
1119
let Normalized {
1085
1120
value : closure_type,
1086
- mut obligations
1121
+ obligations
1087
1122
} = normalize_with_depth ( selcx,
1088
1123
obligation. cause . clone ( ) ,
1089
1124
obligation. recursion_depth +1 ,
1090
1125
& 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)
1097
1131
}
1098
1132
1099
1133
fn confirm_callable_candidate < ' cx , ' gcx , ' tcx > (
1100
1134
selcx : & mut SelectionContext < ' cx , ' gcx , ' tcx > ,
1101
1135
obligation : & ProjectionTyObligation < ' tcx > ,
1102
1136
fn_sig : & ty:: PolyFnSig < ' tcx > ,
1103
1137
flag : util:: TupleArgumentsFlag )
1104
- -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
1138
+ -> Progress < ' tcx >
1105
1139
{
1106
1140
let tcx = selcx. tcx ( ) ;
1107
1141
@@ -1134,47 +1168,38 @@ fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>(
1134
1168
selcx : & mut SelectionContext < ' cx , ' gcx , ' tcx > ,
1135
1169
obligation : & ProjectionTyObligation < ' tcx > ,
1136
1170
poly_projection : ty:: PolyProjectionPredicate < ' tcx > )
1137
- -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
1171
+ -> Progress < ' tcx >
1138
1172
{
1139
1173
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
-
1150
1174
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
1157
1179
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
+ }
1159
1185
}
1160
1186
Err ( e) => {
1161
1187
span_bug ! (
1162
1188
obligation. cause. span,
1163
- "Failed to unify `{:?}` and `{:?}` in projection: {}" ,
1189
+ "Failed to unify obligation `{:?}` \
1190
+ with poly_projection `{:?}`: {:?}",
1164
1191
obligation,
1165
- projection ,
1192
+ poly_projection ,
1166
1193
e) ;
1167
1194
}
1168
- } ;
1169
-
1170
- ( projection. ty , obligations)
1195
+ }
1171
1196
}
1172
1197
1173
1198
fn confirm_impl_candidate < ' cx , ' gcx , ' tcx > (
1174
1199
selcx : & mut SelectionContext < ' cx , ' gcx , ' tcx > ,
1175
1200
obligation : & ProjectionTyObligation < ' tcx > ,
1176
1201
impl_vtable : VtableImplData < ' tcx , PredicateObligation < ' tcx > > )
1177
- -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
1202
+ -> Progress < ' tcx >
1178
1203
{
1179
1204
let VtableImplData { substs, nested, impl_def_id } = impl_vtable;
1180
1205
@@ -1195,7 +1220,11 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
1195
1220
tcx. types . err
1196
1221
} ) ;
1197
1222
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
+ }
1199
1228
}
1200
1229
None => {
1201
1230
span_bug ! ( obligation. cause. span,
0 commit comments