@@ -399,21 +399,31 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
399
399
fake_reads : _,
400
400
} => {
401
401
let closure_id = closure_id. expect_local ( ) ;
402
- let closure_def = if let Some ( ( did, const_param_id) ) =
403
- ty:: WithOptConstParam :: try_lookup ( closure_id, self . tcx )
404
- {
405
- ty:: WithOptConstParam { did, const_param_did : Some ( const_param_id) }
406
- } else {
407
- ty:: WithOptConstParam :: unknown ( closure_id)
408
- } ;
409
- let ( closure_thir, expr) = self . tcx . thir_body ( closure_def) ;
410
- let closure_thir = & closure_thir. borrow ( ) ;
411
- let hir_context = self . tcx . hir ( ) . local_def_id_to_hir_id ( closure_id) ;
412
- let mut closure_visitor =
413
- UnsafetyVisitor { thir : closure_thir, hir_context, ..* self } ;
414
- closure_visitor. visit_expr ( & closure_thir[ expr] ) ;
415
- // Unsafe blocks can be used in closures, make sure to take it into account
416
- self . safety_context = closure_visitor. safety_context ;
402
+ let closure_hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( closure_id) ;
403
+
404
+ // Closures in AnonConsts are handled separately to avoid cycles (issue #87414).
405
+ if !matches ! (
406
+ self . tcx. hir( ) . get( self . tcx. hir( ) . enclosing_body_owner( closure_hir_id) ) ,
407
+ hir:: Node :: AnonConst ( _)
408
+ ) {
409
+ let closure_def = if let Some ( ( did, const_param_id) ) =
410
+ ty:: WithOptConstParam :: try_lookup ( closure_id, self . tcx )
411
+ {
412
+ ty:: WithOptConstParam { did, const_param_did : Some ( const_param_id) }
413
+ } else {
414
+ ty:: WithOptConstParam :: unknown ( closure_id)
415
+ } ;
416
+ let ( closure_thir, expr) = self . tcx . thir_body ( closure_def) ;
417
+ let closure_thir = & closure_thir. borrow ( ) ;
418
+ let mut closure_visitor = UnsafetyVisitor {
419
+ thir : closure_thir,
420
+ hir_context : closure_hir_id,
421
+ ..* self
422
+ } ;
423
+ closure_visitor. visit_expr ( & closure_thir[ expr] ) ;
424
+ // Unsafe blocks can be used in closures, make sure to take it into account
425
+ self . safety_context = closure_visitor. safety_context ;
426
+ }
417
427
}
418
428
ExprKind :: Field { lhs, .. } => {
419
429
let lhs = & self . thir [ lhs] ;
@@ -597,11 +607,19 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
597
607
return ;
598
608
}
599
609
600
- // Closures are handled by their owner, if it has a body
610
+ let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def. did ) ;
611
+
612
+ // Closures are handled by their owner, if it has a body, except if the
613
+ // closure occurs in an AnonConst body to avoid a cycle (issue #87414)
601
614
if tcx. is_closure ( def. did . to_def_id ( ) ) {
602
- let owner = tcx. hir ( ) . local_def_id_to_hir_id ( def. did ) . owner ;
603
- let owner_hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( owner) ;
615
+ let encl_body_owner = tcx. hir ( ) . enclosing_body_owner ( hir_id) ;
616
+ if matches ! ( tcx. hir( ) . get( encl_body_owner) , hir:: Node :: AnonConst ( _) ) {
617
+ tcx. ensure ( ) . thir_check_unsafety ( tcx. hir ( ) . local_def_id ( encl_body_owner) ) ;
618
+ return ;
619
+ }
604
620
621
+ let owner = hir_id. owner ;
622
+ let owner_hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( owner) ;
605
623
if tcx. hir ( ) . maybe_body_owned_by ( owner_hir_id) . is_some ( ) {
606
624
tcx. ensure ( ) . thir_check_unsafety ( owner) ;
607
625
return ;
@@ -615,7 +633,6 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
615
633
return ;
616
634
}
617
635
618
- let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def. did ) ;
619
636
let body_unsafety = tcx. hir ( ) . fn_sig_by_hir_id ( hir_id) . map_or ( BodyUnsafety :: Safe , |fn_sig| {
620
637
if fn_sig. header . unsafety == hir:: Unsafety :: Unsafe {
621
638
BodyUnsafety :: Unsafe ( fn_sig. span )
0 commit comments