@@ -297,25 +297,61 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
297
297
fn try_normalize_ty (
298
298
& mut self ,
299
299
param_env : ty:: ParamEnv < ' tcx > ,
300
- mut ty : Ty < ' tcx > ,
301
- ) -> Result < Option < Ty < ' tcx > > , NoSolution > {
302
- for _ in 0 ..self . local_overflow_limit ( ) {
303
- let ty:: Alias ( _, projection_ty) = * ty. kind ( ) else {
304
- return Ok ( Some ( ty) ) ;
305
- } ;
306
-
307
- let normalized_ty = self . next_ty_infer ( ) ;
300
+ ty : Ty < ' tcx > ,
301
+ ) -> Option < Ty < ' tcx > > {
302
+ self . try_normalize_ty_recur ( param_env, 0 , ty)
303
+ }
304
+
305
+ fn try_normalize_ty_recur (
306
+ & mut self ,
307
+ param_env : ty:: ParamEnv < ' tcx > ,
308
+ depth : usize ,
309
+ ty : Ty < ' tcx > ,
310
+ ) -> Option < Ty < ' tcx > > {
311
+ if depth >= self . local_overflow_limit ( ) {
312
+ return None ;
313
+ }
314
+
315
+ let ty:: Alias ( kind, projection_ty) = * ty. kind ( ) else {
316
+ return Some ( ty) ;
317
+ } ;
318
+
319
+ // We do no always define opaque types eagerly to allow non-defining uses in the defining scope.
320
+ if let ( DefineOpaqueTypes :: No , ty:: AliasKind :: Opaque ) = ( define_opaque_types, kind) {
321
+ if let Some ( def_id) = projection_ty. def_id . as_local ( ) {
322
+ if self
323
+ . unify_existing_opaque_tys (
324
+ param_env,
325
+ OpaqueTypeKey { def_id, args : projection_ty. args } ,
326
+ self . next_ty_infer ( ) ,
327
+ )
328
+ . is_empty ( )
329
+ {
330
+ return Some ( ty) ;
331
+ }
332
+ }
333
+ }
334
+
335
+ // FIXME(@lcnr): If the normalization of the alias adds an inference constraint which
336
+ // causes a previously added goal to fail, then we treat the alias as rigid.
337
+ //
338
+ // These feels like a potential issue, I should look into writing some tests here
339
+ // and then probably changing `commit_if_ok` to not inherit the parent goals.
340
+ match self . commit_if_ok ( |this| {
341
+ let normalized_ty = this. next_ty_infer ( ) ;
308
342
let normalizes_to_goal = Goal :: new (
309
- self . tcx ( ) ,
343
+ this . tcx ( ) ,
310
344
param_env,
311
345
ty:: ProjectionPredicate { projection_ty, term : normalized_ty. into ( ) } ,
312
346
) ;
313
- self . add_goal ( normalizes_to_goal) ;
314
- self . try_evaluate_added_goals ( ) ?;
315
- ty = self . resolve_vars_if_possible ( normalized_ty) ;
347
+ this. add_goal ( normalizes_to_goal) ;
348
+ this. try_evaluate_added_goals ( ) ?;
349
+ let ty = this. resolve_vars_if_possible ( normalized_ty) ;
350
+ Ok ( this. try_normalize_ty_recur ( param_env, depth + 1 , ty) )
351
+ } ) {
352
+ Ok ( ty) => ty,
353
+ Err ( NoSolution ) => Some ( ty) ,
316
354
}
317
-
318
- Ok ( None )
319
355
}
320
356
}
321
357
0 commit comments