88//! or constant found within. (This underlying query is what is cached.) 
99
1010use  crate :: mir; 
11+ use  crate :: traits:: query:: NoSolution ; 
1112use  crate :: ty:: fold:: { TypeFoldable ,  TypeFolder } ; 
1213use  crate :: ty:: subst:: { Subst ,  SubstsRef } ; 
1314use  crate :: ty:: { self ,  Ty ,  TyCtxt } ; 
1415
16+ #[ derive( Debug ,  Copy ,  Clone ,  HashStable ,  TyEncodable ,  TyDecodable ) ]  
17+ pub  enum  NormalizationError < ' tcx >  { 
18+     Type ( Ty < ' tcx > ) , 
19+     Const ( ty:: Const < ' tcx > ) , 
20+     ConstantKind ( mir:: ConstantKind < ' tcx > ) , 
21+ } 
22+ 
23+ impl < ' tcx >  NormalizationError < ' tcx >  { 
24+     pub  fn  get_type_for_failure ( & self )  -> String  { 
25+         match  self  { 
26+             NormalizationError :: Type ( t)  => format ! ( "{}" ,  t) , 
27+             NormalizationError :: Const ( c)  => format ! ( "{}" ,  c) , 
28+             NormalizationError :: ConstantKind ( ck)  => format ! ( "{}" ,  ck) , 
29+         } 
30+     } 
31+ } 
32+ 
1533impl < ' tcx >  TyCtxt < ' tcx >  { 
1634    /// Erase the regions in `value` and then fully normalize all the 
1735/// types found within. The result will also have regions erased. 
@@ -32,6 +50,8 @@ impl<'tcx> TyCtxt<'tcx> {
3250        // Erase first before we do the real query -- this keeps the 
3351        // cache from being too polluted. 
3452        let  value = self . erase_regions ( value) ; 
53+         debug ! ( ?value) ; 
54+ 
3555        if  !value. has_projections ( )  { 
3656            value
3757        }  else  { 
@@ -41,6 +61,39 @@ impl<'tcx> TyCtxt<'tcx> {
4161        } 
4262    } 
4363
64+     /// Tries to erase the regions in `value` and then fully normalize all the 
65+ /// types found within. The result will also have regions erased. 
66+ /// 
67+ /// Contrary to `normalize_erasing_regions` this function does not assume that normalization 
68+ /// succeeds. 
69+ pub  fn  try_normalize_erasing_regions < T > ( 
70+         self , 
71+         param_env :  ty:: ParamEnv < ' tcx > , 
72+         value :  T , 
73+     )  -> Result < T ,  NormalizationError < ' tcx > > 
74+     where 
75+         T :  TypeFoldable < ' tcx > , 
76+     { 
77+         debug ! ( 
78+             "try_normalize_erasing_regions::<{}>(value={:?}, param_env={:?})" , 
79+             std:: any:: type_name:: <T >( ) , 
80+             value, 
81+             param_env, 
82+         ) ; 
83+ 
84+         // Erase first before we do the real query -- this keeps the 
85+         // cache from being too polluted. 
86+         let  value = self . erase_regions ( value) ; 
87+         debug ! ( ?value) ; 
88+ 
89+         if  !value. has_projections ( )  { 
90+             Ok ( value) 
91+         }  else  { 
92+             let  mut  folder = TryNormalizeAfterErasingRegionsFolder :: new ( self ,  param_env) ; 
93+             value. fold_with ( & mut  folder) 
94+         } 
95+     } 
96+ 
4497    /// If you have a `Binder<'tcx, T>`, you can do this to strip out the 
4598/// late-bound regions and then normalize the result, yielding up 
4699/// a `T` (with regions erased). This is appropriate when the 
@@ -91,11 +144,14 @@ struct NormalizeAfterErasingRegionsFolder<'tcx> {
91144} 
92145
93146impl < ' tcx >  NormalizeAfterErasingRegionsFolder < ' tcx >  { 
147+     #[ instrument( skip( self ) ,  level = "debug" ) ]  
94148    fn  normalize_generic_arg_after_erasing_regions ( 
95149        & self , 
96150        arg :  ty:: GenericArg < ' tcx > , 
97151    )  -> ty:: GenericArg < ' tcx >  { 
98152        let  arg = self . param_env . and ( arg) ; 
153+         debug ! ( ?arg) ; 
154+ 
99155        self . tcx . normalize_generic_arg_after_erasing_regions ( arg) 
100156    } 
101157} 
@@ -126,3 +182,62 @@ impl TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> {
126182        Ok ( self . tcx . normalize_mir_const_after_erasing_regions ( arg) ) 
127183    } 
128184} 
185+ 
186+ struct  TryNormalizeAfterErasingRegionsFolder < ' tcx >  { 
187+     tcx :  TyCtxt < ' tcx > , 
188+     param_env :  ty:: ParamEnv < ' tcx > , 
189+ } 
190+ 
191+ impl < ' tcx >  TryNormalizeAfterErasingRegionsFolder < ' tcx >  { 
192+     fn  new ( tcx :  TyCtxt < ' tcx > ,  param_env :  ty:: ParamEnv < ' tcx > )  -> Self  { 
193+         TryNormalizeAfterErasingRegionsFolder  {  tcx,  param_env } 
194+     } 
195+ 
196+     #[ instrument( skip( self ) ,  level = "debug" ) ]  
197+     fn  try_normalize_generic_arg_after_erasing_regions ( 
198+         & self , 
199+         arg :  ty:: GenericArg < ' tcx > , 
200+     )  -> Result < ty:: GenericArg < ' tcx > ,  NoSolution >  { 
201+         let  arg = self . param_env . and ( arg) ; 
202+         debug ! ( ?arg) ; 
203+ 
204+         self . tcx . try_normalize_generic_arg_after_erasing_regions ( arg) 
205+     } 
206+ } 
207+ 
208+ impl  TypeFolder < ' tcx >  for  TryNormalizeAfterErasingRegionsFolder < ' tcx >  { 
209+     type  Error  = NormalizationError < ' tcx > ; 
210+ 
211+     fn  tcx ( & self )  -> TyCtxt < ' tcx >  { 
212+         self . tcx 
213+     } 
214+ 
215+     fn  fold_ty ( & mut  self ,  ty :  Ty < ' tcx > )  -> Result < Ty < ' tcx > ,  Self :: Error >  { 
216+         match  self . try_normalize_generic_arg_after_erasing_regions ( ty. into ( ) )  { 
217+             Ok ( t)  => Ok ( t. expect_ty ( ) ) , 
218+             Err ( _)  => Err ( NormalizationError :: Type ( ty) ) , 
219+         } 
220+     } 
221+ 
222+     fn  fold_const ( 
223+         & mut  self , 
224+         c :  & ' tcx  ty:: Const < ' tcx > , 
225+     )  -> Result < & ' tcx  ty:: Const < ' tcx > ,  Self :: Error >  { 
226+         match  self . try_normalize_generic_arg_after_erasing_regions ( c. into ( ) )  { 
227+             Ok ( t)  => Ok ( t. expect_const ( ) ) , 
228+             Err ( _)  => Err ( NormalizationError :: Const ( * c) ) , 
229+         } 
230+     } 
231+ 
232+     fn  fold_mir_const ( 
233+         & mut  self , 
234+         c :  mir:: ConstantKind < ' tcx > , 
235+     )  -> Result < mir:: ConstantKind < ' tcx > ,  Self :: Error >  { 
236+         // FIXME: This *probably* needs canonicalization too! 
237+         let  arg = self . param_env . and ( c) ; 
238+         match  self . tcx . try_normalize_mir_const_after_erasing_regions ( arg)  { 
239+             Ok ( c)  => Ok ( c) , 
240+             Err ( _)  => Err ( NormalizationError :: ConstantKind ( c) ) , 
241+         } 
242+     } 
243+ } 
0 commit comments