@@ -1391,11 +1391,15 @@ fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed
13911391///
13921392/// If all the return expressions evaluate to `!`, then we explain that the error will go away
13931393/// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder.
1394- fn opaque_type_cycle_error ( tcx : TyCtxt < ' _ > , def_id : LocalDefId , span : Span ) -> ErrorGuaranteed {
1394+ fn opaque_type_cycle_error (
1395+ tcx : TyCtxt < ' _ > ,
1396+ opaque_def_id : LocalDefId ,
1397+ span : Span ,
1398+ ) -> ErrorGuaranteed {
13951399 let mut err = struct_span_err ! ( tcx. sess, span, E0720 , "cannot resolve opaque type" ) ;
13961400
13971401 let mut label = false ;
1398- if let Some ( ( def_id, visitor) ) = get_owner_return_paths ( tcx, def_id ) {
1402+ if let Some ( ( def_id, visitor) ) = get_owner_return_paths ( tcx, opaque_def_id ) {
13991403 let typeck_results = tcx. typeck ( def_id) ;
14001404 if visitor
14011405 . returns
@@ -1431,28 +1435,71 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> E
14311435 . filter_map ( |e| typeck_results. node_type_opt ( e. hir_id ) . map ( |t| ( e. span , t) ) )
14321436 . filter ( |( _, ty) | !matches ! ( ty. kind( ) , ty:: Never ) )
14331437 {
1434- struct OpaqueTypeCollector ( Vec < DefId > ) ;
1438+ #[ derive( Default ) ]
1439+ struct OpaqueTypeCollector {
1440+ opaques : Vec < DefId > ,
1441+ closures : Vec < DefId > ,
1442+ }
14351443 impl < ' tcx > ty:: visit:: TypeVisitor < ' tcx > for OpaqueTypeCollector {
14361444 fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
14371445 match * t. kind ( ) {
14381446 ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id : def, .. } ) => {
1439- self . 0 . push ( def) ;
1447+ self . opaques . push ( def) ;
14401448 ControlFlow :: Continue ( ( ) )
14411449 }
1450+ ty:: Closure ( def_id, ..) | ty:: Generator ( def_id, ..) => {
1451+ self . closures . push ( def_id) ;
1452+ t. super_visit_with ( self )
1453+ }
14421454 _ => t. super_visit_with ( self ) ,
14431455 }
14441456 }
14451457 }
1446- let mut visitor = OpaqueTypeCollector ( vec ! [ ] ) ;
1458+
1459+ let mut visitor = OpaqueTypeCollector :: default ( ) ;
14471460 ty. visit_with ( & mut visitor) ;
1448- for def_id in visitor. 0 {
1461+ for def_id in visitor. opaques {
14491462 let ty_span = tcx. def_span ( def_id) ;
14501463 if !seen. contains ( & ty_span) {
14511464 err. span_label ( ty_span, & format ! ( "returning this opaque type `{ty}`" ) ) ;
14521465 seen. insert ( ty_span) ;
14531466 }
14541467 err. span_label ( sp, & format ! ( "returning here with type `{ty}`" ) ) ;
14551468 }
1469+
1470+ for closure_def_id in visitor. closures {
1471+ let Some ( closure_local_did) = closure_def_id. as_local ( ) else { continue ; } ;
1472+ let typeck_results = tcx. typeck ( closure_local_did) ;
1473+
1474+ let mut label_match = |ty : Ty < ' _ > , span| {
1475+ for arg in ty. walk ( ) {
1476+ if let ty:: GenericArgKind :: Type ( ty) = arg. unpack ( )
1477+ && let ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id : captured_def_id, .. } ) = * ty. kind ( )
1478+ && captured_def_id == opaque_def_id. to_def_id ( )
1479+ {
1480+ err. span_label (
1481+ span,
1482+ format ! (
1483+ "{} captures itself here" ,
1484+ tcx. def_kind( closure_def_id) . descr( closure_def_id)
1485+ ) ,
1486+ ) ;
1487+ }
1488+ }
1489+ } ;
1490+
1491+ // Label any closure upvars that capture the opaque
1492+ for capture in typeck_results. closure_min_captures_flattened ( closure_local_did)
1493+ {
1494+ label_match ( capture. place . ty ( ) , capture. get_path_span ( tcx) ) ;
1495+ }
1496+ // Label any generator locals that capture the opaque
1497+ for interior_ty in
1498+ typeck_results. generator_interior_types . as_ref ( ) . skip_binder ( )
1499+ {
1500+ label_match ( interior_ty. ty , interior_ty. span ) ;
1501+ }
1502+ }
14561503 }
14571504 }
14581505 }
0 commit comments