@@ -10,6 +10,7 @@ use super::PredicateObligation;
10
10
use super :: Selection ;
11
11
use super :: SelectionContext ;
12
12
use super :: SelectionError ;
13
+ use super :: TraitQueryMode ;
13
14
use super :: {
14
15
ImplSourceClosureData , ImplSourceDiscriminantKindData , ImplSourceFnPointerData ,
15
16
ImplSourceGeneratorData , ImplSourcePointeeData , ImplSourceUserDefinedData ,
@@ -18,7 +19,7 @@ use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
18
19
19
20
use crate :: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
20
21
use crate :: infer:: { InferCtxt , InferOk , LateBoundRegionConversionTime } ;
21
- use crate :: traits:: error_reporting:: InferCtxtExt ;
22
+ use crate :: traits:: error_reporting:: InferCtxtExt as _ ;
22
23
use rustc_data_structures:: stack:: ensure_sufficient_stack;
23
24
use rustc_errors:: ErrorReported ;
24
25
use rustc_hir:: def_id:: DefId ;
@@ -912,6 +913,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
912
913
}
913
914
914
915
let obligation = Obligation :: with_depth ( cause. clone ( ) , depth, param_env, projection_ty) ;
916
+
915
917
match project_type ( selcx, & obligation) {
916
918
Ok ( ProjectedTy :: Progress ( Progress {
917
919
ty : projected_ty,
@@ -925,7 +927,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
925
927
let projected_ty = selcx. infcx ( ) . resolve_vars_if_possible ( projected_ty) ;
926
928
debug ! ( ?projected_ty, ?depth, ?projected_obligations) ;
927
929
928
- let result = if projected_ty. has_projections ( ) {
930
+ let mut result = if projected_ty. has_projections ( ) {
929
931
let mut normalizer = AssocTypeNormalizer :: new (
930
932
selcx,
931
933
param_env,
@@ -942,8 +944,26 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
942
944
Normalized { value : projected_ty, obligations : projected_obligations }
943
945
} ;
944
946
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 ( ) ) ;
947
967
obligations. extend ( result. obligations ) ;
948
968
Ok ( Some ( result. value ) )
949
969
}
@@ -974,49 +994,6 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
974
994
}
975
995
}
976
996
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
-
1020
997
/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
1021
998
/// hold. In various error cases, we cannot generate a valid
1022
999
/// normalized projection. Therefore, we create an inference variable
0 commit comments