11use crate :: check:: intrinsicck:: InlineAsmCtxt ;
2- use crate :: errors:: LinkageType ;
32
43use super :: compare_impl_item:: check_type_bounds;
54use super :: compare_impl_item:: { compare_impl_method, compare_impl_ty} ;
65use super :: * ;
76use rustc_attr as attr;
7+ use rustc_data_structures:: unord:: UnordSet ;
88use rustc_errors:: { codes:: * , MultiSpan } ;
99use rustc_hir as hir;
1010use rustc_hir:: def:: { CtorKind , DefKind } ;
1111use rustc_hir:: Node ;
1212use rustc_infer:: infer:: { RegionVariableOrigin , TyCtxtInferExt } ;
1313use rustc_infer:: traits:: { Obligation , TraitEngineExt as _} ;
1414use rustc_lint_defs:: builtin:: REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS ;
15+ use rustc_middle:: middle:: resolve_bound_vars:: ResolvedArg ;
1516use rustc_middle:: middle:: stability:: EvalResult ;
1617use rustc_middle:: traits:: ObligationCauseCode ;
1718use rustc_middle:: ty:: fold:: BottomUpFolder ;
@@ -474,6 +475,94 @@ fn sanity_check_found_hidden_type<'tcx>(
474475 }
475476}
476477
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+
477566fn is_enum_of_nonnullable_ptr < ' tcx > (
478567 tcx : TyCtxt < ' tcx > ,
479568 adt_def : AdtDef < ' tcx > ,
@@ -499,7 +588,7 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
499588 ty:: Adt ( adt_def, args) => !is_enum_of_nonnullable_ptr ( tcx, * adt_def, * args) ,
500589 _ => true ,
501590 } {
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) } ) ;
503592 }
504593 }
505594}
@@ -566,6 +655,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
566655 check_union ( tcx, def_id) ;
567656 }
568657 DefKind :: OpaqueTy => {
658+ check_opaque_precise_captures ( tcx, def_id) ;
659+
569660 let origin = tcx. opaque_type_origin ( def_id) ;
570661 if let hir:: OpaqueTyOrigin :: FnReturn ( fn_def_id)
571662 | hir:: OpaqueTyOrigin :: AsyncFn ( fn_def_id) = origin
0 commit comments