1
1
use 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 } ;
7
3
use rustc_macros:: extension;
8
4
use rustc_middle:: ty:: {
9
- self , GenericArgKind , GenericArgs , OpaqueHiddenType , OpaqueTypeKey , Ty , TyCtxt , TypeFoldable ,
10
- TypeVisitableExt , TypingMode , fold_regions,
5
+ self , OpaqueHiddenType , OpaqueTypeKey , Ty , TyCtxt , TypeFoldable , TypeVisitableExt , fold_regions,
11
6
} ;
12
7
use rustc_span:: Span ;
13
- use rustc_trait_selection:: regions:: OutlivesEnvironmentBuildExt ;
14
- use rustc_trait_selection:: traits:: ObligationCtxt ;
8
+ use rustc_trait_selection:: opaque_types:: check_opaque_type_parameter_valid;
15
9
use tracing:: { debug, instrument} ;
16
10
17
11
use super :: RegionInferenceContext ;
18
12
use crate :: opaque_types:: ConcreteOpaqueTypes ;
19
- use crate :: session_diagnostics:: { LifetimeMismatchOpaqueParam , NonGenericOpaqueTypeParam } ;
13
+ use crate :: session_diagnostics:: LifetimeMismatchOpaqueParam ;
20
14
use crate :: universal_regions:: RegionClassification ;
21
15
22
16
impl < ' tcx > RegionInferenceContext < ' tcx > {
@@ -273,7 +267,7 @@ impl<'tcx> InferCtxt<'tcx> {
273
267
}
274
268
275
269
if let Err ( guar) =
276
- check_opaque_type_parameter_valid ( self , opaque_type_key, instantiated_ty. span )
270
+ check_opaque_type_parameter_valid ( self , opaque_type_key, instantiated_ty. span , false )
277
271
{
278
272
return Ty :: new_error ( self . tcx , guar) ;
279
273
}
@@ -289,156 +283,3 @@ impl<'tcx> InferCtxt<'tcx> {
289
283
definition_ty
290
284
}
291
285
}
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