11use rustc_data_structures:: fx:: FxIndexMap ;
2- use rustc_errors:: ErrorGuaranteed ;
3- use rustc_hir:: OpaqueTyOrigin ;
4- use rustc_hir:: def_id:: LocalDefId ;
5- use rustc_infer:: infer:: outlives:: env:: OutlivesEnvironment ;
6- use rustc_infer:: infer:: { InferCtxt , NllRegionVariableOrigin , TyCtxtInferExt as _} ;
2+ use rustc_infer:: infer:: { InferCtxt , NllRegionVariableOrigin } ;
73use rustc_macros:: extension;
84use rustc_middle:: ty:: {
9- self , GenericArgKind , GenericArgs , OpaqueHiddenType , OpaqueTypeKey , Ty , TyCtxt , TypeFoldable ,
10- TypeVisitableExt , TypingMode , fold_regions,
5+ self , DefiningScopeKind , OpaqueHiddenType , OpaqueTypeKey , Ty , TyCtxt , TypeFoldable ,
6+ TypeVisitableExt , fold_regions,
117} ;
128use rustc_span:: Span ;
13- use rustc_trait_selection:: regions:: OutlivesEnvironmentBuildExt ;
14- use rustc_trait_selection:: traits:: ObligationCtxt ;
9+ use rustc_trait_selection:: opaque_types:: check_opaque_type_parameter_valid;
1510use tracing:: { debug, instrument} ;
1611
1712use super :: RegionInferenceContext ;
1813use crate :: opaque_types:: ConcreteOpaqueTypes ;
19- use crate :: session_diagnostics:: { LifetimeMismatchOpaqueParam , NonGenericOpaqueTypeParam } ;
14+ use crate :: session_diagnostics:: LifetimeMismatchOpaqueParam ;
2015use crate :: universal_regions:: RegionClassification ;
2116
2217impl < ' tcx > RegionInferenceContext < ' tcx > {
@@ -272,14 +267,21 @@ impl<'tcx> InferCtxt<'tcx> {
272267 return Ty :: new_error ( self . tcx , e) ;
273268 }
274269
275- if let Err ( guar) =
276- check_opaque_type_parameter_valid ( self , opaque_type_key, instantiated_ty. span )
277- {
270+ if let Err ( guar) = check_opaque_type_parameter_valid (
271+ self ,
272+ opaque_type_key,
273+ instantiated_ty. span ,
274+ DefiningScopeKind :: MirBorrowck ,
275+ ) {
278276 return Ty :: new_error ( self . tcx , guar) ;
279277 }
280278
281279 let definition_ty = instantiated_ty
282- . remap_generic_params_to_declaration_params ( opaque_type_key, self . tcx , false )
280+ . remap_generic_params_to_declaration_params (
281+ opaque_type_key,
282+ self . tcx ,
283+ DefiningScopeKind :: MirBorrowck ,
284+ )
283285 . ty ;
284286
285287 if let Err ( e) = definition_ty. error_reported ( ) {
@@ -289,156 +291,3 @@ impl<'tcx> InferCtxt<'tcx> {
289291 definition_ty
290292 }
291293}
292-
293- /// Opaque type parameter validity check as documented in the [rustc-dev-guide chapter].
294- ///
295- /// [rustc-dev-guide chapter]:
296- /// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
297- fn check_opaque_type_parameter_valid < ' tcx > (
298- infcx : & InferCtxt < ' tcx > ,
299- opaque_type_key : OpaqueTypeKey < ' tcx > ,
300- span : Span ,
301- ) -> Result < ( ) , ErrorGuaranteed > {
302- let tcx = infcx. tcx ;
303- let opaque_generics = tcx. generics_of ( opaque_type_key. def_id ) ;
304- let opaque_env = LazyOpaqueTyEnv :: new ( tcx, opaque_type_key. def_id ) ;
305- let mut seen_params: FxIndexMap < _ , Vec < _ > > = FxIndexMap :: default ( ) ;
306-
307- for ( i, arg) in opaque_type_key. iter_captured_args ( tcx) {
308- let arg_is_param = match arg. unpack ( ) {
309- GenericArgKind :: Type ( ty) => matches ! ( ty. kind( ) , ty:: Param ( _) ) ,
310- GenericArgKind :: Lifetime ( lt) => {
311- matches ! ( * lt, ty:: ReEarlyParam ( _) | ty:: ReLateParam ( _) )
312- || ( lt. is_static ( ) && opaque_env. param_equal_static ( i) )
313- }
314- GenericArgKind :: Const ( ct) => matches ! ( ct. kind( ) , ty:: ConstKind :: Param ( _) ) ,
315- } ;
316-
317- if arg_is_param {
318- // Register if the same lifetime appears multiple times in the generic args.
319- // There is an exception when the opaque type *requires* the lifetimes to be equal.
320- // See [rustc-dev-guide chapter] § "An exception to uniqueness rule".
321- let seen_where = seen_params. entry ( arg) . or_default ( ) ;
322- if !seen_where. first ( ) . is_some_and ( |& prev_i| opaque_env. params_equal ( i, prev_i) ) {
323- seen_where. push ( i) ;
324- }
325- } else {
326- // Prevent `fn foo() -> Foo<u32>` from being defining.
327- let opaque_param = opaque_generics. param_at ( i, tcx) ;
328- let kind = opaque_param. kind . descr ( ) ;
329-
330- opaque_env. param_is_error ( i) ?;
331-
332- return Err ( infcx. dcx ( ) . emit_err ( NonGenericOpaqueTypeParam {
333- ty : arg,
334- kind,
335- span,
336- param_span : tcx. def_span ( opaque_param. def_id ) ,
337- } ) ) ;
338- }
339- }
340-
341- for ( _, indices) in seen_params {
342- if indices. len ( ) > 1 {
343- let descr = opaque_generics. param_at ( indices[ 0 ] , tcx) . kind . descr ( ) ;
344- let spans: Vec < _ > = indices
345- . into_iter ( )
346- . map ( |i| tcx. def_span ( opaque_generics. param_at ( i, tcx) . def_id ) )
347- . collect ( ) ;
348- #[ allow( rustc:: diagnostic_outside_of_impl) ]
349- #[ allow( rustc:: untranslatable_diagnostic) ]
350- return Err ( infcx
351- . dcx ( )
352- . struct_span_err ( span, "non-defining opaque type use in defining scope" )
353- . with_span_note ( spans, format ! ( "{descr} used multiple times" ) )
354- . emit ( ) ) ;
355- }
356- }
357-
358- Ok ( ( ) )
359- }
360-
361- /// Computes if an opaque type requires a lifetime parameter to be equal to
362- /// another one or to the `'static` lifetime.
363- /// These requirements are derived from the explicit and implied bounds.
364- struct LazyOpaqueTyEnv < ' tcx > {
365- tcx : TyCtxt < ' tcx > ,
366- def_id : LocalDefId ,
367-
368- /// Equal parameters will have the same name. Computed Lazily.
369- /// Example:
370- /// `type Opaque<'a: 'static, 'b: 'c, 'c: 'b> = impl Sized;`
371- /// Identity args: `['a, 'b, 'c]`
372- /// Canonical args: `['static, 'b, 'b]`
373- canonical_args : std:: cell:: OnceCell < ty:: GenericArgsRef < ' tcx > > ,
374- }
375-
376- impl < ' tcx > LazyOpaqueTyEnv < ' tcx > {
377- fn new ( tcx : TyCtxt < ' tcx > , def_id : LocalDefId ) -> Self {
378- Self { tcx, def_id, canonical_args : std:: cell:: OnceCell :: new ( ) }
379- }
380-
381- fn param_equal_static ( & self , param_index : usize ) -> bool {
382- self . get_canonical_args ( ) [ param_index] . expect_region ( ) . is_static ( )
383- }
384-
385- fn params_equal ( & self , param1 : usize , param2 : usize ) -> bool {
386- let canonical_args = self . get_canonical_args ( ) ;
387- canonical_args[ param1] == canonical_args[ param2]
388- }
389-
390- fn param_is_error ( & self , param_index : usize ) -> Result < ( ) , ErrorGuaranteed > {
391- self . get_canonical_args ( ) [ param_index] . error_reported ( )
392- }
393-
394- fn get_canonical_args ( & self ) -> ty:: GenericArgsRef < ' tcx > {
395- if let Some ( & canonical_args) = self . canonical_args . get ( ) {
396- return canonical_args;
397- }
398-
399- let & Self { tcx, def_id, .. } = self ;
400- let origin = tcx. local_opaque_ty_origin ( def_id) ;
401- let parent = match origin {
402- OpaqueTyOrigin :: FnReturn { parent, .. }
403- | OpaqueTyOrigin :: AsyncFn { parent, .. }
404- | OpaqueTyOrigin :: TyAlias { parent, .. } => parent,
405- } ;
406- let param_env = tcx. param_env ( parent) ;
407- let args = GenericArgs :: identity_for_item ( tcx, parent) . extend_to (
408- tcx,
409- def_id. to_def_id ( ) ,
410- |param, _| {
411- tcx. map_opaque_lifetime_to_parent_lifetime ( param. def_id . expect_local ( ) ) . into ( )
412- } ,
413- ) ;
414-
415- // FIXME(#132279): It feels wrong to use `non_body_analysis` here given that we're
416- // in a body here.
417- let infcx = tcx. infer_ctxt ( ) . build ( TypingMode :: non_body_analysis ( ) ) ;
418- let ocx = ObligationCtxt :: new ( & infcx) ;
419-
420- let wf_tys = ocx. assumed_wf_types ( param_env, parent) . unwrap_or_else ( |_| {
421- tcx. dcx ( ) . span_delayed_bug ( tcx. def_span ( def_id) , "error getting implied bounds" ) ;
422- Default :: default ( )
423- } ) ;
424- let outlives_env = OutlivesEnvironment :: new ( & infcx, parent, param_env, wf_tys) ;
425-
426- let mut seen = vec ! [ tcx. lifetimes. re_static] ;
427- let canonical_args = fold_regions ( tcx, args, |r1, _| {
428- if r1. is_error ( ) {
429- r1
430- } else if let Some ( & r2) = seen. iter ( ) . find ( |& & r2| {
431- let free_regions = outlives_env. free_region_map ( ) ;
432- free_regions. sub_free_regions ( tcx, r1, r2)
433- && free_regions. sub_free_regions ( tcx, r2, r1)
434- } ) {
435- r2
436- } else {
437- seen. push ( r1) ;
438- r1
439- }
440- } ) ;
441- self . canonical_args . set ( canonical_args) . unwrap ( ) ;
442- canonical_args
443- }
444- }
0 commit comments