@@ -10,6 +10,7 @@ use super::PredicateObligation;
1010use super :: Selection ;
1111use super :: SelectionContext ;
1212use super :: SelectionError ;
13+ use super :: TraitQueryMode ;
1314use super :: {
1415 ImplSourceClosureData , ImplSourceDiscriminantKindData , ImplSourceFnPointerData ,
1516 ImplSourceGeneratorData , ImplSourcePointeeData , ImplSourceUserDefinedData ,
@@ -18,7 +19,7 @@ use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
1819
1920use crate :: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
2021use crate :: infer:: { InferCtxt , InferOk , LateBoundRegionConversionTime } ;
21- use crate :: traits:: error_reporting:: InferCtxtExt ;
22+ use crate :: traits:: error_reporting:: InferCtxtExt as _ ;
2223use rustc_data_structures:: stack:: ensure_sufficient_stack;
2324use rustc_errors:: ErrorReported ;
2425use rustc_hir:: def_id:: DefId ;
@@ -912,6 +913,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
912913 }
913914
914915 let obligation = Obligation :: with_depth ( cause. clone ( ) , depth, param_env, projection_ty) ;
916+
915917 match project_type ( selcx, & obligation) {
916918 Ok ( ProjectedTy :: Progress ( Progress {
917919 ty : projected_ty,
@@ -925,7 +927,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
925927 let projected_ty = selcx. infcx ( ) . resolve_vars_if_possible ( projected_ty) ;
926928 debug ! ( ?projected_ty, ?depth, ?projected_obligations) ;
927929
928- let result = if projected_ty. has_projections ( ) {
930+ let mut result = if projected_ty. has_projections ( ) {
929931 let mut normalizer = AssocTypeNormalizer :: new (
930932 selcx,
931933 param_env,
@@ -942,8 +944,26 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
942944 Normalized { value : projected_ty, obligations : projected_obligations }
943945 } ;
944946
945- let cache_value = prune_cache_value_obligations ( infcx, & result) ;
946- infcx. inner . borrow_mut ( ) . projection_cache ( ) . insert_ty ( cache_key, cache_value) ;
947+ let mut canonical =
948+ SelectionContext :: with_query_mode ( selcx. infcx ( ) , TraitQueryMode :: Canonical ) ;
949+ result. obligations . drain_filter ( |projected_obligation| {
950+ // If any global obligations always apply, considering regions, then we don't
951+ // need to include them. The `is_global` check rules out inference variables,
952+ // so there's no need for the caller of `opt_normalize_projection_type`
953+ // to evaluate them.
954+ // Note that we do *not* discard obligations that evaluate to
955+ // `EvaluatedtoOkModuloRegions`. Evaluating these obligations
956+ // inside of a query (e.g. `evaluate_obligation`) can change
957+ // the result to `EvaluatedToOkModuloRegions`, while an
958+ // `EvaluatedToOk` obligation will never change the result.
959+ // See #85360 for more details
960+ projected_obligation. is_global ( canonical. tcx ( ) )
961+ && canonical
962+ . evaluate_root_obligation ( projected_obligation)
963+ . map_or ( false , |res| res. must_apply_considering_regions ( ) )
964+ } ) ;
965+
966+ infcx. inner . borrow_mut ( ) . projection_cache ( ) . insert_ty ( cache_key, result. clone ( ) ) ;
947967 obligations. extend ( result. obligations ) ;
948968 Ok ( Some ( result. value ) )
949969 }
@@ -974,49 +994,6 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
974994 }
975995}
976996
977- /// If there are unresolved type variables, then we need to include
978- /// any subobligations that bind them, at least until those type
979- /// variables are fully resolved.
980- fn prune_cache_value_obligations < ' a , ' tcx > (
981- infcx : & ' a InferCtxt < ' a , ' tcx > ,
982- result : & NormalizedTy < ' tcx > ,
983- ) -> NormalizedTy < ' tcx > {
984- if infcx. unresolved_type_vars ( & result. value ) . is_none ( ) {
985- return NormalizedTy { value : result. value , obligations : vec ! [ ] } ;
986- }
987-
988- let mut obligations: Vec < _ > = result
989- . obligations
990- . iter ( )
991- . filter ( |obligation| {
992- let bound_predicate = obligation. predicate . kind ( ) ;
993- match bound_predicate. skip_binder ( ) {
994- // We found a `T: Foo<X = U>` predicate, let's check
995- // if `U` references any unresolved type
996- // variables. In principle, we only care if this
997- // projection can help resolve any of the type
998- // variables found in `result.value` -- but we just
999- // check for any type variables here, for fear of
1000- // indirect obligations (e.g., we project to `?0`,
1001- // but we have `T: Foo<X = ?1>` and `?1: Bar<X =
1002- // ?0>`).
1003- ty:: PredicateKind :: Projection ( data) => {
1004- infcx. unresolved_type_vars ( & bound_predicate. rebind ( data. ty ) ) . is_some ( )
1005- }
1006-
1007- // We are only interested in `T: Foo<X = U>` predicates, whre
1008- // `U` references one of `unresolved_type_vars`. =)
1009- _ => false ,
1010- }
1011- } )
1012- . cloned ( )
1013- . collect ( ) ;
1014-
1015- obligations. shrink_to_fit ( ) ;
1016-
1017- NormalizedTy { value : result. value , obligations }
1018- }
1019-
1020997/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
1021998/// hold. In various error cases, we cannot generate a valid
1022999/// normalized projection. Therefore, we create an inference variable
0 commit comments