1
1
use rustc_infer:: infer:: TyCtxtInferExt ;
2
2
use rustc_middle:: traits:: query:: NoSolution ;
3
3
use rustc_middle:: ty:: query:: Providers ;
4
- use rustc_middle:: ty:: { self , ParamEnvAnd , TyCtxt , TypeFoldable } ;
4
+ use rustc_middle:: ty:: {
5
+ self , FallibleTypeFolder , ParamEnvAnd , Ty , TyCtxt , TypeFoldable , TypeSuperFoldable , TypeVisitable ,
6
+ } ;
5
7
use rustc_trait_selection:: traits:: query:: normalize:: AtExt ;
6
8
use rustc_trait_selection:: traits:: { Normalized , ObligationCause } ;
7
9
use std:: sync:: atomic:: Ordering ;
@@ -16,17 +18,33 @@ pub(crate) fn provide(p: &mut Providers) {
16
18
. normalize_generic_arg_after_erasing_regions
17
19
. fetch_add ( 1 , Ordering :: Relaxed ) ;
18
20
19
- try_normalize_after_erasing_regions ( tcx, goal)
21
+ let ParamEnvAnd { param_env, value } = goal;
22
+
23
+ match value. unpack ( ) {
24
+ ty:: GenericArgKind :: Type ( ty) => {
25
+ let ty =
26
+ ty. try_super_fold_with ( & mut NormalizeDeeperFolder { tcx, param_env } ) ?;
27
+ if let ty:: Projection ( ..) | ty:: Opaque ( ..) = ty. kind ( ) {
28
+ Ok ( try_normalize_after_erasing_regions ( tcx, param_env, ty) ?. into ( ) )
29
+ } else {
30
+ Ok ( ty. into ( ) )
31
+ }
32
+ }
33
+ ty:: GenericArgKind :: Const ( _) => {
34
+ try_normalize_after_erasing_regions ( tcx, param_env, value)
35
+ }
36
+ ty:: GenericArgKind :: Lifetime ( _) => unreachable ! ( ) ,
37
+ }
20
38
} ,
21
39
..* p
22
40
} ;
23
41
}
24
42
25
43
fn try_normalize_after_erasing_regions < ' tcx , T : TypeFoldable < ' tcx > + PartialEq + Copy > (
26
44
tcx : TyCtxt < ' tcx > ,
27
- goal : ParamEnvAnd < ' tcx , T > ,
45
+ param_env : ty:: ParamEnv < ' tcx > ,
46
+ value : T ,
28
47
) -> Result < T , NoSolution > {
29
- let ParamEnvAnd { param_env, value } = goal;
30
48
let infcx = tcx. infer_ctxt ( ) . ignoring_regions ( ) . build ( ) ;
31
49
let cause = ObligationCause :: dummy ( ) ;
32
50
match infcx. at ( & cause, param_env) . normalize ( value) {
@@ -52,6 +70,39 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq +
52
70
}
53
71
}
54
72
73
+ struct NormalizeDeeperFolder < ' tcx > {
74
+ tcx : TyCtxt < ' tcx > ,
75
+ param_env : ty:: ParamEnv < ' tcx > ,
76
+ }
77
+
78
+ impl < ' tcx > FallibleTypeFolder < ' tcx > for NormalizeDeeperFolder < ' tcx > {
79
+ type Error = NoSolution ;
80
+
81
+ fn tcx ( & self ) -> TyCtxt < ' tcx > {
82
+ self . tcx
83
+ }
84
+
85
+ fn try_fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Result < Ty < ' tcx > , Self :: Error > {
86
+ if !ty. needs_normalization ( self . param_env . reveal ( ) ) {
87
+ return Ok ( ty) ;
88
+ }
89
+
90
+ let ty = ty. try_super_fold_with ( self ) ?;
91
+ if let ty:: Projection ( ..) | ty:: Opaque ( ..) = ty. kind ( ) {
92
+ Ok ( self
93
+ . tcx
94
+ . try_normalize_generic_arg_after_erasing_regions ( self . param_env . and ( ty. into ( ) ) ) ?
95
+ . expect_ty ( ) )
96
+ } else {
97
+ Ok ( ty)
98
+ }
99
+ }
100
+
101
+ fn try_fold_const ( & mut self , c : ty:: Const < ' tcx > ) -> Result < ty:: Const < ' tcx > , Self :: Error > {
102
+ try_normalize_after_erasing_regions ( self . tcx , self . param_env , c)
103
+ }
104
+ }
105
+
55
106
fn not_outlives_predicate < ' tcx > ( p : ty:: Predicate < ' tcx > ) -> bool {
56
107
match p. kind ( ) . skip_binder ( ) {
57
108
ty:: PredicateKind :: RegionOutlives ( ..) | ty:: PredicateKind :: TypeOutlives ( ..) => false ,
0 commit comments