1
1
use crate :: check:: intrinsicck:: InlineAsmCtxt ;
2
- use crate :: errors:: LinkageType ;
3
2
4
3
use super :: compare_impl_item:: check_type_bounds;
5
4
use super :: compare_impl_item:: { compare_impl_method, compare_impl_ty} ;
6
5
use super :: * ;
7
6
use rustc_attr as attr;
7
+ use rustc_data_structures:: unord:: UnordSet ;
8
8
use rustc_errors:: { codes:: * , MultiSpan } ;
9
9
use rustc_hir as hir;
10
10
use rustc_hir:: def:: { CtorKind , DefKind } ;
11
11
use rustc_hir:: Node ;
12
12
use rustc_infer:: infer:: { RegionVariableOrigin , TyCtxtInferExt } ;
13
13
use rustc_infer:: traits:: { Obligation , TraitEngineExt as _} ;
14
14
use rustc_lint_defs:: builtin:: REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS ;
15
+ use rustc_middle:: middle:: resolve_bound_vars:: ResolvedArg ;
15
16
use rustc_middle:: middle:: stability:: EvalResult ;
16
17
use rustc_middle:: traits:: ObligationCauseCode ;
17
18
use rustc_middle:: ty:: fold:: BottomUpFolder ;
@@ -474,6 +475,94 @@ fn sanity_check_found_hidden_type<'tcx>(
474
475
}
475
476
}
476
477
478
+ fn check_opaque_precise_captures < ' tcx > ( tcx : TyCtxt < ' tcx > , opaque_def_id : LocalDefId ) {
479
+ let hir:: OpaqueTy { precise_capturing_args, .. } =
480
+ * tcx. hir_node_by_def_id ( opaque_def_id) . expect_item ( ) . expect_opaque_ty ( ) ;
481
+ let Some ( precise_capturing_args) = precise_capturing_args else {
482
+ // No precise capturing args; nothing to validate
483
+ return ;
484
+ } ;
485
+
486
+ let mut expected_captures = UnordSet :: default ( ) ;
487
+ for arg in precise_capturing_args {
488
+ match * arg {
489
+ hir:: PreciseCapturingArg :: Lifetime ( & hir:: Lifetime { hir_id, .. } )
490
+ | hir:: PreciseCapturingArg :: Param ( _, hir_id) => match tcx. named_bound_var ( hir_id) {
491
+ Some ( ResolvedArg :: EarlyBound ( def_id) ) => {
492
+ expected_captures. insert ( def_id) ;
493
+ }
494
+ _ => {
495
+ tcx. dcx ( ) . span_delayed_bug (
496
+ tcx. hir ( ) . span ( hir_id) ,
497
+ "parameter should have been resolved" ,
498
+ ) ;
499
+ }
500
+ } ,
501
+ }
502
+ }
503
+
504
+ let variances = tcx. variances_of ( opaque_def_id) ;
505
+ let mut def_id = Some ( opaque_def_id. to_def_id ( ) ) ;
506
+ while let Some ( generics) = def_id {
507
+ let generics = tcx. generics_of ( generics) ;
508
+ def_id = generics. parent ;
509
+
510
+ for param in & generics. params {
511
+ if expected_captures. contains ( & param. def_id ) {
512
+ assert_eq ! (
513
+ variances[ param. index as usize ] ,
514
+ ty:: Invariant ,
515
+ "precise captured param should be invariant"
516
+ ) ;
517
+ continue ;
518
+ }
519
+
520
+ match param. kind {
521
+ ty:: GenericParamDefKind :: Lifetime => {
522
+ // Check if the lifetime param was captured but isn't named in the precise captures list.
523
+ if variances[ param. index as usize ] == ty:: Invariant {
524
+ let param_span =
525
+ if let ty:: ReEarlyParam ( ty:: EarlyParamRegion { def_id, .. } )
526
+ | ty:: ReLateParam ( ty:: LateParamRegion {
527
+ bound_region : ty:: BoundRegionKind :: BrNamed ( def_id, _) ,
528
+ ..
529
+ } ) = * tcx
530
+ . map_opaque_lifetime_to_parent_lifetime ( param. def_id . expect_local ( ) )
531
+ {
532
+ Some ( tcx. def_span ( def_id) )
533
+ } else {
534
+ None
535
+ } ;
536
+ // FIXME(precise_capturing): Structured suggestion for this would be useful
537
+ tcx. dcx ( ) . emit_err ( errors:: LifetimeNotCaptured {
538
+ use_span : tcx. def_span ( param. def_id ) ,
539
+ param_span,
540
+ opaque_span : tcx. def_span ( opaque_def_id) ,
541
+ } ) ;
542
+ continue ;
543
+ }
544
+ }
545
+ ty:: GenericParamDefKind :: Type { .. } => {
546
+ // FIXME(precise_capturing): Structured suggestion for this would be useful
547
+ tcx. dcx ( ) . emit_err ( errors:: ParamNotCaptured {
548
+ param_span : tcx. def_span ( param. def_id ) ,
549
+ opaque_span : tcx. def_span ( opaque_def_id) ,
550
+ kind : "type" ,
551
+ } ) ;
552
+ }
553
+ ty:: GenericParamDefKind :: Const { .. } => {
554
+ // FIXME(precise_capturing): Structured suggestion for this would be useful
555
+ tcx. dcx ( ) . emit_err ( errors:: ParamNotCaptured {
556
+ param_span : tcx. def_span ( param. def_id ) ,
557
+ opaque_span : tcx. def_span ( opaque_def_id) ,
558
+ kind : "const" ,
559
+ } ) ;
560
+ }
561
+ }
562
+ }
563
+ }
564
+ }
565
+
477
566
fn is_enum_of_nonnullable_ptr < ' tcx > (
478
567
tcx : TyCtxt < ' tcx > ,
479
568
adt_def : AdtDef < ' tcx > ,
@@ -499,7 +588,7 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
499
588
ty:: Adt ( adt_def, args) => !is_enum_of_nonnullable_ptr ( tcx, * adt_def, * args) ,
500
589
_ => true ,
501
590
} {
502
- tcx. dcx ( ) . emit_err ( LinkageType { span : tcx. def_span ( def_id) } ) ;
591
+ tcx. dcx ( ) . emit_err ( errors :: LinkageType { span : tcx. def_span ( def_id) } ) ;
503
592
}
504
593
}
505
594
}
@@ -566,6 +655,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
566
655
check_union ( tcx, def_id) ;
567
656
}
568
657
DefKind :: OpaqueTy => {
658
+ check_opaque_precise_captures ( tcx, def_id) ;
659
+
569
660
let origin = tcx. opaque_type_origin ( def_id) ;
570
661
if let hir:: OpaqueTyOrigin :: FnReturn ( fn_def_id)
571
662
| hir:: OpaqueTyOrigin :: AsyncFn ( fn_def_id) = origin
0 commit comments