@@ -1391,11 +1391,15 @@ fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed
1391
1391
///
1392
1392
/// If all the return expressions evaluate to `!`, then we explain that the error will go away
1393
1393
/// 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 {
1395
1399
let mut err = struct_span_err ! ( tcx. sess, span, E0720 , "cannot resolve opaque type" ) ;
1396
1400
1397
1401
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 ) {
1399
1403
let typeck_results = tcx. typeck ( def_id) ;
1400
1404
if visitor
1401
1405
. returns
@@ -1431,28 +1435,71 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> E
1431
1435
. filter_map ( |e| typeck_results. node_type_opt ( e. hir_id ) . map ( |t| ( e. span , t) ) )
1432
1436
. filter ( |( _, ty) | !matches ! ( ty. kind( ) , ty:: Never ) )
1433
1437
{
1434
- struct OpaqueTypeCollector ( Vec < DefId > ) ;
1438
+ #[ derive( Default ) ]
1439
+ struct OpaqueTypeCollector {
1440
+ opaques : Vec < DefId > ,
1441
+ closures : Vec < DefId > ,
1442
+ }
1435
1443
impl < ' tcx > ty:: visit:: TypeVisitor < ' tcx > for OpaqueTypeCollector {
1436
1444
fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
1437
1445
match * t. kind ( ) {
1438
1446
ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id : def, .. } ) => {
1439
- self . 0 . push ( def) ;
1447
+ self . opaques . push ( def) ;
1440
1448
ControlFlow :: Continue ( ( ) )
1441
1449
}
1450
+ ty:: Closure ( def_id, ..) | ty:: Generator ( def_id, ..) => {
1451
+ self . closures . push ( def_id) ;
1452
+ t. super_visit_with ( self )
1453
+ }
1442
1454
_ => t. super_visit_with ( self ) ,
1443
1455
}
1444
1456
}
1445
1457
}
1446
- let mut visitor = OpaqueTypeCollector ( vec ! [ ] ) ;
1458
+
1459
+ let mut visitor = OpaqueTypeCollector :: default ( ) ;
1447
1460
ty. visit_with ( & mut visitor) ;
1448
- for def_id in visitor. 0 {
1461
+ for def_id in visitor. opaques {
1449
1462
let ty_span = tcx. def_span ( def_id) ;
1450
1463
if !seen. contains ( & ty_span) {
1451
1464
err. span_label ( ty_span, & format ! ( "returning this opaque type `{ty}`" ) ) ;
1452
1465
seen. insert ( ty_span) ;
1453
1466
}
1454
1467
err. span_label ( sp, & format ! ( "returning here with type `{ty}`" ) ) ;
1455
1468
}
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
+ }
1456
1503
}
1457
1504
}
1458
1505
}
0 commit comments