1
- use rustc_data_structures:: fx:: FxIndexMap ;
1
+ use rustc_data_structures:: fx:: { FxIndexMap , IndexEntry } ;
2
2
use rustc_errors:: ErrorGuaranteed ;
3
3
use rustc_hir:: def:: DefKind ;
4
4
use rustc_hir:: def_id:: LocalDefId ;
@@ -352,12 +352,7 @@ fn check_opaque_type_parameter_valid<'tcx>(
352
352
opaque_type_key : OpaqueTypeKey < ' tcx > ,
353
353
span : Span ,
354
354
) -> Result < ( ) , ErrorGuaranteed > {
355
- let opaque_ty_hir = tcx. hir ( ) . expect_item ( opaque_type_key. def_id ) ;
356
- let is_ty_alias = match opaque_ty_hir. expect_opaque_ty ( ) . origin {
357
- OpaqueTyOrigin :: TyAlias { .. } => true ,
358
- OpaqueTyOrigin :: AsyncFn ( ..) | OpaqueTyOrigin :: FnReturn ( ..) => false ,
359
- } ;
360
-
355
+ let canonical_args = get_canonical_key ( tcx, opaque_type_key. def_id ) . args ;
361
356
let opaque_generics = tcx. generics_of ( opaque_type_key. def_id ) ;
362
357
let mut seen_params: FxIndexMap < _ , Vec < _ > > = FxIndexMap :: default ( ) ;
363
358
for ( i, arg) in opaque_type_key. iter_captured_args ( tcx) {
@@ -367,20 +362,24 @@ fn check_opaque_type_parameter_valid<'tcx>(
367
362
368
363
let arg_is_param = match arg. unpack ( ) {
369
364
GenericArgKind :: Type ( ty) => matches ! ( ty. kind( ) , ty:: Param ( _) ) ,
370
- GenericArgKind :: Lifetime ( lt) => match is_ty_alias {
371
- true => matches ! ( * lt, ty:: ReEarlyBound ( _) | ty:: ReFree ( _) ) ,
372
- // FIXME(#111935, #113916): For RPIT, we currently accept ReStatic as well.
373
- // This is a back-compat hack, see the issue for more.
374
- false => matches ! ( * lt, ty:: ReEarlyBound ( _) | ty:: ReFree ( _) | ty:: ReStatic ) ,
375
- } ,
365
+ GenericArgKind :: Lifetime ( lt) => {
366
+ matches ! ( * lt, ty:: ReEarlyBound ( _) | ty:: ReFree ( _) )
367
+ || ( lt. is_static ( ) && canonical_args[ i] . expect_region ( ) . is_static ( ) )
368
+ }
376
369
GenericArgKind :: Const ( ct) => matches ! ( ct. kind( ) , ty:: ConstKind :: Param ( _) ) ,
377
370
} ;
378
371
379
372
if arg_is_param {
380
- // FIXME(#113916): For RPIT, we can't currently check for unique lifetime
381
- // params, see that issue for more. We limit this to TAIT for now.
382
- if is_ty_alias {
383
- seen_params. entry ( arg) . or_default ( ) . push ( i) ;
373
+ match seen_params. entry ( arg) {
374
+ IndexEntry :: Vacant ( e) => {
375
+ e. insert ( vec ! [ i] ) ;
376
+ }
377
+ IndexEntry :: Occupied ( mut e) => {
378
+ let prev_i = e. get ( ) [ 0 ] ;
379
+ if canonical_args[ i] != canonical_args[ prev_i] {
380
+ e. get_mut ( ) . push ( i) ;
381
+ }
382
+ }
384
383
}
385
384
} else {
386
385
// Prevent `fn foo() -> Foo<u32>` from being defining.
@@ -413,3 +412,48 @@ fn check_opaque_type_parameter_valid<'tcx>(
413
412
414
413
Ok ( ( ) )
415
414
}
415
+
416
+ fn get_canonical_key < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : LocalDefId ) -> OpaqueTypeKey < ' tcx > {
417
+ use rustc_hir as hir;
418
+ use rustc_infer:: infer:: outlives:: env:: OutlivesEnvironment ;
419
+ use rustc_trait_selection:: traits:: outlives_bounds:: InferCtxtExt as _;
420
+
421
+ let origin = & tcx. opaque_type_origin ( def_id) ;
422
+ let defining_use_anchor = match * origin {
423
+ hir:: OpaqueTyOrigin :: FnReturn ( did) | hir:: OpaqueTyOrigin :: AsyncFn ( did) => did,
424
+ hir:: OpaqueTyOrigin :: TyAlias { .. } => tcx. impl_trait_parent ( def_id) ,
425
+ } ;
426
+ let param_env = tcx. param_env ( defining_use_anchor) ;
427
+
428
+ let infcx = tcx. infer_ctxt ( ) . build ( ) ;
429
+ let ocx = ObligationCtxt :: new ( & infcx) ;
430
+
431
+ let args = match * origin {
432
+ hir:: OpaqueTyOrigin :: FnReturn ( parent) | hir:: OpaqueTyOrigin :: AsyncFn ( parent) => {
433
+ GenericArgs :: identity_for_item ( tcx, parent) . extend_to (
434
+ tcx,
435
+ def_id. to_def_id ( ) ,
436
+ |param, _| tcx. map_rpit_lifetime_to_fn_lifetime ( param. def_id . expect_local ( ) ) . into ( ) ,
437
+ )
438
+ }
439
+ hir:: OpaqueTyOrigin :: TyAlias { .. } => GenericArgs :: identity_for_item ( tcx, def_id) ,
440
+ } ;
441
+
442
+ let wf_tys = ocx. assumed_wf_types ( param_env, defining_use_anchor) . unwrap_or_default ( ) ;
443
+ let implied_bounds = infcx. implied_bounds_tys ( param_env, defining_use_anchor, wf_tys) ;
444
+ let outlives_env = OutlivesEnvironment :: with_bounds ( param_env, implied_bounds) ;
445
+ let free_regions = outlives_env. free_region_map ( ) ;
446
+
447
+ let mut seen = vec ! [ tcx. lifetimes. re_static] ;
448
+ OpaqueTypeKey { def_id, args } . fold_captured_lifetime_args ( tcx, |region| {
449
+ if let Some ( & r2) = seen. iter ( ) . find ( |& & r2| {
450
+ free_regions. sub_free_regions ( tcx, region, r2)
451
+ && free_regions. sub_free_regions ( tcx, r2, region)
452
+ } ) {
453
+ r2
454
+ } else {
455
+ seen. push ( region) ;
456
+ region
457
+ }
458
+ } )
459
+ }
0 commit comments