@@ -3,7 +3,7 @@ use crate::hir;
3
3
use crate :: hir:: Node ;
4
4
use crate :: infer:: { self , InferCtxt , InferOk , TypeVariableOrigin } ;
5
5
use crate :: infer:: outlives:: free_region_map:: FreeRegionRelations ;
6
- use rustc_data_structures:: fx:: FxHashMap ;
6
+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
7
7
use crate :: traits:: { self , PredicateObligation } ;
8
8
use crate :: ty:: { self , Ty , TyCtxt , GenericParamDefKind } ;
9
9
use crate :: ty:: fold:: { BottomUpFolder , TypeFoldable , TypeFolder } ;
@@ -276,84 +276,87 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
276
276
opaque_defn : & OpaqueTypeDecl < ' tcx > ,
277
277
free_region_relations : & FRR ,
278
278
) {
279
- debug ! ( "constrain_opaque_type()" ) ;
280
- debug ! ( "constrain_opaque_type: def_id={:?}" , def_id) ;
281
- debug ! ( "constrain_opaque_type: opaque_defn={:#?}" , opaque_defn) ;
279
+ debug ! ( "constrain_opaque_type(def_id={:?}, opaque_defn={:#?})" , def_id, opaque_defn) ;
282
280
283
281
let concrete_ty = self . resolve_type_vars_if_possible ( & opaque_defn. concrete_ty ) ;
284
282
285
283
debug ! ( "constrain_opaque_type: concrete_ty={:?}" , concrete_ty) ;
286
284
287
- let abstract_type_generics = self . tcx . generics_of ( def_id) ;
285
+ let opaque_type_generics = self . tcx . generics_of ( def_id) ;
288
286
289
287
let span = self . tcx . def_span ( def_id) ;
290
288
291
289
// If there are required region bounds, we can just skip
292
- // ahead. There will already be a registered region
293
- // obligation related `concrete_ty` to those regions.
294
- if opaque_defn. has_required_region_bounds {
295
- return ;
296
- }
297
-
298
- // There were no `required_region_bounds`,
299
- // so we have to search for a `least_region`.
300
- // Go through all the regions used as arguments to the
301
- // abstract type. These are the parameters to the abstract
302
- // type; so in our example above, `substs` would contain
303
- // `['a]` for the first impl trait and `'b` for the
304
- // second.
305
- let mut least_region = None ;
306
- for param in & abstract_type_generics . params {
307
- match param . kind {
308
- GenericParamDefKind :: Lifetime => { }
309
- _ => continue
310
- }
311
- // Get the value supplied for this region from the substs.
312
- let subst_arg = opaque_defn . substs . region_at ( param . index as usize ) ;
313
-
314
- // Compute the least upper bound of it with the other regions.
315
- debug ! ( "constrain_opaque_types: least_region ={:?}" , least_region ) ;
316
- debug ! ( "constrain_opaque_types: subst_arg={:?}" , subst_arg ) ;
317
- match least_region {
318
- None => least_region = Some ( subst_arg ) ,
319
- Some ( lr) => {
320
- if free_region_relations . sub_free_regions ( lr , subst_arg ) {
321
- // keep the current least region
322
- } else if free_region_relations . sub_free_regions ( subst_arg , lr ) {
323
- // switch to ` subst_arg`
324
- least_region = Some ( subst_arg ) ;
325
- } else {
326
- // There are two regions (`lr` and
327
- // `subst_arg`) which are not relatable. We can't
328
- // find a best choice.
329
- self . tcx
330
- . sess
331
- . struct_span_err ( span , "ambiguous lifetime bound in `impl Trait`" )
332
- . span_label (
333
- span ,
334
- format ! ( "neither `{}` nor `{}` outlives the other" , lr , subst_arg ) ,
335
- )
336
- . emit ( ) ;
337
-
338
- least_region = Some ( self . tcx . mk_region ( ty :: ReEmpty ) ) ;
339
- break ;
290
+ // ahead. There will already be a registered region
291
+ // obligation relating `concrete_ty` to those regions.
292
+ let least_region = if opaque_defn. has_required_region_bounds {
293
+ None
294
+ } else {
295
+ // There were no `required_region_bounds`,
296
+ // so we have to search for a `least_region`.
297
+ // Go through all the regions used as arguments to the
298
+ // existential type. These are the parameters to the existential
299
+ // type; so in our example above, `substs` would contain
300
+ // `['a]` for the first impl trait and `'b` for the
301
+ // second.
302
+ let mut least_region = None ;
303
+ for param in & opaque_type_generics . params {
304
+ match param . kind {
305
+ GenericParamDefKind :: Lifetime => { }
306
+ _ => continue
307
+ }
308
+ // Get the value supplied for this region from the substs.
309
+ let subst_arg = opaque_defn . substs . region_at ( param . index as usize ) ;
310
+
311
+ // Compute the least upper bound of it with the other regions.
312
+ debug ! ( "constrain_opaque_type: least_region={:?}" , least_region ) ;
313
+ debug ! ( "constrain_opaque_type: subst_arg ={:?}" , subst_arg ) ;
314
+ match least_region {
315
+ None => least_region = Some ( subst_arg ) ,
316
+ Some ( lr ) => {
317
+ if free_region_relations . sub_free_regions ( lr, subst_arg ) {
318
+ // Keep the current least region.
319
+ } else if free_region_relations . sub_free_regions ( subst_arg , lr ) {
320
+ // Switch to `subst_arg`.
321
+ least_region = Some ( subst_arg) ;
322
+ } else {
323
+ // There are two regions (`lr` and `subst_arg`) that are not relatable.
324
+ // We can't find a best choice.
325
+ self . tcx
326
+ . sess
327
+ . struct_span_err ( span , "ambiguous lifetime bound in `impl Trait`" )
328
+ . span_label (
329
+ span ,
330
+ format ! ( "neither `{}` nor `{}` outlives the other" ,
331
+ lr , subst_arg ) ,
332
+ )
333
+ . emit ( ) ;
334
+
335
+ least_region = Some ( self . tcx . mk_region ( ty :: ReEmpty ) ) ;
336
+ break ;
337
+ }
340
338
}
341
339
}
342
340
}
343
- }
344
-
345
- let least_region = least_region. unwrap_or ( self . tcx . types . re_static ) ;
346
- debug ! ( "constrain_opaque_types: least_region={:?}" , least_region) ;
341
+ least_region
342
+ } . unwrap_or ( self . tcx . types . re_static ) ;
343
+ debug ! ( "constrain_opaque_type: least_region={:?}" , least_region) ;
347
344
348
345
// Require that the type `concrete_ty` outlives
349
346
// `least_region`, modulo any type parameters that appear
350
- // in the type, which we ignore. This is because impl
351
- // trait values are assumed to capture all the in-scope
347
+ // in the type, which we ignore. This is because ` impl
348
+ // Trait` values are assumed to capture all the in-scope
352
349
// type parameters. This little loop here just invokes
353
350
// `outlives` repeatedly, draining all the nested
354
351
// obligations that result.
352
+ let mut concrete_ty_regions = FxHashSet :: default ( ) ;
355
353
let mut types = vec ! [ concrete_ty] ;
356
- let bound_region = |r| self . sub_regions ( infer:: CallReturn ( span) , least_region, r) ;
354
+ let mut bound_region = |r| {
355
+ concrete_ty_regions. insert ( r) ;
356
+ if !opaque_defn. has_required_region_bounds {
357
+ self . sub_regions ( infer:: CallReturn ( span) , least_region, r)
358
+ }
359
+ } ;
357
360
while let Some ( ty) = types. pop ( ) {
358
361
let mut components = smallvec ! [ ] ;
359
362
self . tcx . push_outlives_components ( ty, & mut components) ;
@@ -485,49 +488,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
485
488
486
489
struct ReverseMapper < ' cx , ' gcx : ' tcx , ' tcx : ' cx > {
487
490
tcx : TyCtxt < ' cx , ' gcx , ' tcx > ,
488
-
489
- /// If errors have already been reported in this fn, we suppress
490
- /// our own errors because they are sometimes derivative.
491
- tainted_by_errors : bool ,
492
-
493
- opaque_type_def_id : DefId ,
494
491
map : FxHashMap < Kind < ' tcx > , Kind < ' gcx > > ,
495
- map_missing_regions_to_empty : bool ,
496
-
497
- /// initially `Some`, set to `None` once error has been reported
498
- hidden_ty : Option < Ty < ' tcx > > ,
499
- }
500
-
501
- impl < ' cx , ' gcx , ' tcx > ReverseMapper < ' cx , ' gcx , ' tcx > {
502
- fn new (
503
- tcx : TyCtxt < ' cx , ' gcx , ' tcx > ,
504
- tainted_by_errors : bool ,
505
- opaque_type_def_id : DefId ,
506
- map : FxHashMap < Kind < ' tcx > , Kind < ' gcx > > ,
507
- hidden_ty : Ty < ' tcx > ,
508
- ) -> Self {
509
- Self {
510
- tcx,
511
- tainted_by_errors,
512
- opaque_type_def_id,
513
- map,
514
- map_missing_regions_to_empty : false ,
515
- hidden_ty : Some ( hidden_ty) ,
516
- }
517
- }
518
-
519
- fn fold_kind_mapping_missing_regions_to_empty ( & mut self , kind : Kind < ' tcx > ) -> Kind < ' tcx > {
520
- assert ! ( !self . map_missing_regions_to_empty) ;
521
- self . map_missing_regions_to_empty = true ;
522
- let kind = kind. fold_with ( self ) ;
523
- self . map_missing_regions_to_empty = false ;
524
- kind
525
- }
526
-
527
- fn fold_kind_normally ( & mut self , kind : Kind < ' tcx > ) -> Kind < ' tcx > {
528
- assert ! ( !self . map_missing_regions_to_empty) ;
529
- kind. fold_with ( self )
530
- }
531
492
}
532
493
533
494
impl < ' cx , ' gcx , ' tcx > TypeFolder < ' gcx , ' tcx > for ReverseMapper < ' cx , ' gcx , ' tcx > {
@@ -537,109 +498,53 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx>
537
498
538
499
fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
539
500
match r {
540
- // ignore bound regions that appear in the type (e.g., this
501
+ // Ignore bound regions that appear in the type (e.g., this
541
502
// would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
542
503
ty:: ReLateBound ( ..) |
543
504
544
- // ignore `'static`, as that can appear anywhere
505
+ // Ignore `'static`, as that can appear anywhere.
545
506
ty:: ReStatic |
546
507
547
- // ignore `ReScope`, as that can appear anywhere
548
- // See `src/test/run-pass/issue-49556.rs` for example.
508
+ // Ignore `ReScope`, as that can appear anywhere.
509
+ // See `src/test/run-pass/issue-49556.rs`, for example.
549
510
ty:: ReScope ( ..) => return r,
550
511
551
- _ => { }
512
+ _ => { }
552
513
}
553
514
554
515
match self . map . get ( & r. into ( ) ) . map ( |k| k. unpack ( ) ) {
555
516
Some ( UnpackedKind :: Lifetime ( r1) ) => r1,
556
517
Some ( u) => panic ! ( "region mapped to unexpected kind: {:?}" , u) ,
557
518
None => {
558
- if !self . map_missing_regions_to_empty && !self . tainted_by_errors {
559
- if let Some ( hidden_ty) = self . hidden_ty . take ( ) {
560
- let span = self . tcx . def_span ( self . opaque_type_def_id ) ;
561
- let mut err = struct_span_err ! (
562
- self . tcx. sess,
563
- span,
564
- E0700 ,
565
- "hidden type for `impl Trait` captures lifetime that \
566
- does not appear in bounds",
567
- ) ;
568
-
569
- // Assuming regionck succeeded, then we must
570
- // be capturing *some* region from the fn
571
- // header, and hence it must be free, so it's
572
- // ok to invoke this fn (which doesn't accept
573
- // all regions, and would ICE if an
574
- // inappropriate region is given). We check
575
- // `is_tainted_by_errors` by errors above, so
576
- // we don't get in here unless regionck
577
- // succeeded. (Note also that if regionck
578
- // failed, then the regions we are attempting
579
- // to map here may well be giving errors
580
- // *because* the constraints were not
581
- // satisfiable.)
582
- self . tcx . note_and_explain_free_region (
583
- & mut err,
584
- & format ! ( "hidden type `{}` captures " , hidden_ty) ,
585
- r,
586
- ""
587
- ) ;
588
-
589
- err. emit ( ) ;
590
- }
591
- }
519
+ // No mapping was found. This means that it is either a
520
+ // disallowed lifetime, which will be caught by regionck,
521
+ // a region in a non-upvar closure generic, which is
522
+ // explicitly allowed (see below for more on this),
523
+ // or a lifetime that does not explicitly appear in
524
+ // `impl Trait` bounds but which outlives the lifetimes
525
+ // or types which *do* appear in the `impl Trait` bounds.
526
+ //
527
+ // These lifetimes are explicitly allowed to prevent
528
+ // the user from having to add dummy references to the
529
+ // unnamed lifetimes in their `impl Trait` bounds
530
+ // (e.g., `+ DummyTraitWithALifetimeArg<'a>`). Adding
531
+ // the lifetimes via `+` doesn't work because the type
532
+ // doesn't outlive those lifetimes, it just contains them.
533
+ //
534
+ // On closures: there is a somewhat subtle (read: hacky)
535
+ // consideration. The problem is that our closure types
536
+ // currently include all the lifetime parameters declared
537
+ // on the enclosing function, even if they are unused by
538
+ // the closure itself. We can't readily filter them out,
539
+ // so we replace them with `empty`. This can't really make
540
+ // a diference to the rest of hte compiler; those regions
541
+ // are ignored for the outlives relation, and hence don't
542
+ // affect trait selection or auto traits, and they are
543
+ // erased during trans.
592
544
self . tcx . types . re_empty
593
545
} ,
594
546
}
595
547
}
596
-
597
- fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
598
- match ty. sty {
599
- ty:: Closure ( def_id, substs) => {
600
- // I am a horrible monster and I pray for death. When
601
- // we encounter a closure here, it is always a closure
602
- // from within the function that we are currently
603
- // type-checking -- one that is now being encapsulated
604
- // in an existential abstract type. Ideally, we would
605
- // go through the types/lifetimes that it references
606
- // and treat them just like we would any other type,
607
- // which means we would error out if we find any
608
- // reference to a type/region that is not in the
609
- // "reverse map".
610
- //
611
- // **However,** in the case of closures, there is a
612
- // somewhat subtle (read: hacky) consideration. The
613
- // problem is that our closure types currently include
614
- // all the lifetime parameters declared on the
615
- // enclosing function, even if they are unused by the
616
- // closure itself. We can't readily filter them out,
617
- // so here we replace those values with `'empty`. This
618
- // can't really make a difference to the rest of the
619
- // compiler; those regions are ignored for the
620
- // outlives relation, and hence don't affect trait
621
- // selection or auto traits, and they are erased
622
- // during codegen.
623
-
624
- let generics = self . tcx . generics_of ( def_id) ;
625
- let substs = self . tcx . mk_substs ( substs. substs . iter ( ) . enumerate ( ) . map (
626
- |( index, & kind) | {
627
- if index < generics. parent_count {
628
- // Accommodate missing regions in the parent kinds...
629
- self . fold_kind_mapping_missing_regions_to_empty ( kind)
630
- } else {
631
- // ...but not elsewhere.
632
- self . fold_kind_normally ( kind)
633
- }
634
- } ,
635
- ) ) ;
636
-
637
- self . tcx . mk_closure ( def_id, ty:: ClosureSubsts { substs } )
638
- }
639
-
640
- _ => ty. super_fold_with ( self ) ,
641
- }
642
- }
643
548
}
644
549
645
550
struct Instantiator < ' a , ' gcx : ' tcx , ' tcx : ' a > {
0 commit comments