@@ -66,6 +66,13 @@ struct BoundVarContext<'a, 'tcx> {
6666 rbv : & ' a mut ResolveBoundVars ,
6767 disambiguator : & ' a mut DisambiguatorState ,
6868 scope : ScopeRef < ' a > ,
69+ opaque_capture_errors : RefCell < Option < OpaqueHigherRankedLifetimeCaptureErrors > > ,
70+ }
71+
72+ struct OpaqueHigherRankedLifetimeCaptureErrors {
73+ bad_place : & ' static str ,
74+ capture_spans : Vec < Span > ,
75+ decl_spans : Vec < Span > ,
6976}
7077
7178#[ derive( Debug ) ]
@@ -253,6 +260,7 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou
253260 rbv : & mut rbv,
254261 scope : & Scope :: Root { opt_parent_item : None } ,
255262 disambiguator : & mut DisambiguatorState :: new ( ) ,
263+ opaque_capture_errors : RefCell :: new ( None ) ,
256264 } ;
257265 match tcx. hir_owner_node ( local_def_id) {
258266 hir:: OwnerNode :: Item ( item) => visitor. visit_item ( item) ,
@@ -597,6 +605,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
597605 } )
598606 } ) ;
599607
608+ self . emit_opaque_capture_errors ( ) ;
609+
600610 let captures = captures. into_inner ( ) . into_iter ( ) . collect ( ) ;
601611 debug ! ( ?captures) ;
602612 self . rbv . opaque_captured_lifetimes . insert ( opaque. def_id , captures) ;
@@ -1089,12 +1099,20 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
10891099 F : for < ' b > FnOnce ( & mut BoundVarContext < ' b , ' tcx > ) ,
10901100 {
10911101 let BoundVarContext { tcx, rbv, disambiguator, .. } = self ;
1092- let mut this = BoundVarContext { tcx : * tcx, rbv, disambiguator, scope : & wrap_scope } ;
1102+ let nested_errors = RefCell :: new ( self . opaque_capture_errors . borrow_mut ( ) . take ( ) ) ;
1103+ let mut this = BoundVarContext {
1104+ tcx : * tcx,
1105+ rbv,
1106+ disambiguator,
1107+ scope : & wrap_scope,
1108+ opaque_capture_errors : nested_errors,
1109+ } ;
10931110 let span = debug_span ! ( "scope" , scope = ?this. scope. debug_truncated( ) ) ;
10941111 {
10951112 let _enter = span. enter ( ) ;
10961113 f ( & mut this) ;
10971114 }
1115+ * self . opaque_capture_errors . borrow_mut ( ) = this. opaque_capture_errors . into_inner ( ) ;
10981116 }
10991117
11001118 fn record_late_bound_vars ( & mut self , hir_id : HirId , binder : Vec < ty:: BoundVariableKind > ) {
@@ -1424,21 +1442,52 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
14241442 } ;
14251443
14261444 let decl_span = self . tcx . def_span ( lifetime_def_id) ;
1427- let ( span, label) = if capture_span != decl_span {
1428- ( capture_span, None )
1429- } else {
1430- let opaque_span = self . tcx . def_span ( opaque_def_id) ;
1431- ( opaque_span, Some ( opaque_span) )
1432- } ;
1445+ let opaque_span = self . tcx . def_span ( opaque_def_id) ;
1446+
1447+ let mut errors = self . opaque_capture_errors . borrow_mut ( ) ;
1448+ let error_info = errors. get_or_insert_with ( || OpaqueHigherRankedLifetimeCaptureErrors {
1449+ bad_place,
1450+ capture_spans : Vec :: new ( ) ,
1451+ decl_spans : Vec :: new ( ) ,
1452+ } ) ;
1453+
1454+ if error_info. capture_spans . is_empty ( ) {
1455+ error_info. capture_spans . push ( opaque_span) ;
1456+ }
1457+
1458+ if capture_span != decl_span && capture_span != opaque_span {
1459+ error_info. capture_spans . push ( capture_span) ;
1460+ }
1461+
1462+ if !error_info. decl_spans . contains ( & decl_span) {
1463+ error_info. decl_spans . push ( decl_span) ;
1464+ }
1465+
1466+ // Errors should be emitted by `emit_opaque_capture_errors`.
1467+ Err ( self . tcx . dcx ( ) . span_delayed_bug ( capture_span, "opaque capture error not emitted" ) )
1468+ }
1469+
1470+ fn emit_opaque_capture_errors ( & self ) -> Option < ErrorGuaranteed > {
1471+ let errors = self . opaque_capture_errors . borrow_mut ( ) . take ( ) ?;
1472+ if errors. capture_spans . is_empty ( ) {
1473+ return None ;
1474+ }
1475+
1476+ let mut span = rustc_errors:: MultiSpan :: from_span ( errors. capture_spans [ 0 ] ) ;
1477+ for & capture_span in & errors. capture_spans [ 1 ..] {
1478+ span. push_span_label ( capture_span, "" ) ;
1479+ }
1480+ let decl_span = rustc_errors:: MultiSpan :: from_spans ( errors. decl_spans ) ;
14331481
14341482 // Ensure that the parent of the def is an item, not HRTB
14351483 let guar = self . tcx . dcx ( ) . emit_err ( errors:: OpaqueCapturesHigherRankedLifetime {
14361484 span,
1437- label,
1485+ label : Some ( errors . capture_spans [ 0 ] ) ,
14381486 decl_span,
1439- bad_place,
1487+ bad_place : errors . bad_place ,
14401488 } ) ;
1441- Err ( guar)
1489+
1490+ Some ( guar)
14421491 }
14431492
14441493 #[ instrument( level = "trace" , skip( self , opaque_capture_scopes) , ret) ]
0 commit comments