@@ -338,11 +338,14 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
338
338
debug ! ( "visit_fn_body body.id {:?} call_site_scope: {:?}" ,
339
339
body. id( ) , call_site_scope) ;
340
340
let call_site_region = self . tcx . mk_region ( ty:: ReScope ( call_site_scope) ) ;
341
+
341
342
let body_hir_id = self . tcx . hir . node_to_hir_id ( body_id. node_id ) ;
342
343
self . type_of_node_must_outlive ( infer:: CallReturn ( span) ,
343
344
body_hir_id,
344
345
call_site_region) ;
345
346
347
+ self . constrain_anon_types ( ) ;
348
+
346
349
self . region_bound_pairs . truncate ( old_region_bounds_pairs_len) ;
347
350
348
351
self . set_body_id ( old_body_id) ;
@@ -387,6 +390,140 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
387
390
|| infer:: RelateParamBound ( cause. span , sup_type) )
388
391
}
389
392
393
+ /// Go through each of the existential `impl Trait` types that
394
+ /// appear in the function signature. For example, if the current
395
+ /// function is as follows:
396
+ ///
397
+ /// fn foo<'a, 'b>(..) -> (impl Bar<'a>, impl Bar<'b>)
398
+ ///
399
+ /// we would iterate through the `impl Bar<'a>` and the
400
+ /// `impl Bar<'b>` here. Remember that each of them has
401
+ /// their own "abstract type" definition created for them. As
402
+ /// we iterate, we have a `def_id` that corresponds to this
403
+ /// definition, and a set of substitutions `substs` that are
404
+ /// being supplied to this abstract typed definition in the
405
+ /// signature:
406
+ ///
407
+ /// abstract type Foo1<'x>: Bar<'x>;
408
+ /// abstract type Foo2<'x>: Bar<'x>;
409
+ /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
410
+ /// ^^^^ ^^ substs
411
+ /// def_id
412
+ ///
413
+ /// In addition, for each of the types we will have a type
414
+ /// variable `concrete_ty` containing the concrete type that
415
+ /// this function uses for `Foo1` and `Foo2`. That is,
416
+ /// conceptually, there is a constraint like:
417
+ ///
418
+ /// for<'a> (Foo1<'a> = C)
419
+ ///
420
+ /// where `C` is `concrete_ty`. For this equation to be satisfiable,
421
+ /// the type `C` can only refer to two regions: `'static` and `'a`.
422
+ ///
423
+ /// The problem is that this type `C` may contain arbitrary
424
+ /// region variables. In fact, it is fairly likely that it
425
+ /// does! Consider this possible definition of `foo`:
426
+ ///
427
+ /// fn foo<'a, 'b>(x: &'a i32, y: &'b i32) -> (impl Bar<'a>, impl Bar<'b>) {
428
+ /// (&*x, &*y)
429
+ /// }
430
+ ///
431
+ /// Here, the values for the concrete types of the two impl
432
+ /// traits will include inference variables:
433
+ ///
434
+ /// &'0 i32
435
+ /// &'1 i32
436
+ ///
437
+ /// Ordinarily, the subtyping rules would ensure that these are
438
+ /// sufficiently large. But since `impl Bar<'a>` isn't a specific
439
+ /// type per se, we don't get such constraints by default. This
440
+ /// is where this function comes into play. It adds extra
441
+ /// constraints to ensure that all the regions which appear in the
442
+ /// inferred type are regions that could validly appear.
443
+ ///
444
+ /// This is actually a bit of a tricky constraint in general. We
445
+ /// want to say that each variable (e.g., `'0``) can only take on
446
+ /// values that were supplied as arguments to the abstract type
447
+ /// (e.g., `'a` for `Foo1<'a>`) or `'static`, which is always in
448
+ /// scope. We don't have a constraint quite of this kind in the current
449
+ /// region checker.
450
+ ///
451
+ /// What we *do* have is the `<=` relation. So what we do is to
452
+ /// find the LUB of all the arguments that appear in the substs:
453
+ /// in this case, that would be `LUB('a) = 'a`, and then we apply
454
+ /// that as a least bound to the variables (e.g., `'a <= '0`).
455
+ ///
456
+ /// In some cases this is pretty suboptimal. Consider this example:
457
+ ///
458
+ /// fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... }
459
+ ///
460
+ /// Here, the regions `'a` and `'b` appear in the substitutions,
461
+ /// so we would generate `LUB('a, 'b)` as a kind of "minimal upper
462
+ /// bound", but that turns out be `'static` -- which is clearly
463
+ /// too strict!
464
+ fn constrain_anon_types ( & mut self ) {
465
+ debug ! ( "constrain_anon_types()" ) ;
466
+
467
+ for ( & def_id, anon_defn) in self . fcx . anon_types . borrow ( ) . iter ( ) {
468
+ let concrete_ty = self . resolve_type ( anon_defn. concrete_ty ) ;
469
+
470
+ debug ! ( "constrain_anon_types: def_id={:?}" , def_id) ;
471
+ debug ! ( "constrain_anon_types: substs={:?}" , anon_defn. substs) ;
472
+ debug ! ( "constrain_anon_types: concrete_ty={:?}" , concrete_ty) ;
473
+
474
+ let abstract_type_generics = self . tcx . generics_of ( def_id) ;
475
+
476
+ // Go through all the regions used as arguments to the
477
+ // abstract type. These are the parameters to the abstract
478
+ // type; so in our example above, `substs` would contain
479
+ // `['a]` for the first impl trait and `'b` for the
480
+ // second.
481
+ let mut bound_region = None ;
482
+ for region_def in & abstract_type_generics. regions {
483
+ // Find the index of this region in the list of substitutions.
484
+ let index = region_def. index as usize ;
485
+
486
+ // Get the value supplied for this region from the substs.
487
+ let subst_arg = anon_defn. substs [ index] . as_region ( ) . unwrap ( ) ;
488
+
489
+ // Compute the least upper bound of it with the other regions.
490
+ debug ! ( "constrain_anon_types: bound_region={:?}" , bound_region) ;
491
+ debug ! ( "constrain_anon_types: subst_arg={:?}" , subst_arg) ;
492
+ if let Some ( r) = bound_region {
493
+ let lub = self . free_region_map . lub_free_regions ( self . tcx ,
494
+ r,
495
+ subst_arg) ;
496
+ bound_region = Some ( lub) ;
497
+
498
+ if let ty:: ReStatic = * lub {
499
+ // If LUB results in `'static`, we might as well
500
+ // stop iterating here.
501
+ //
502
+ // FIXME: We might consider issuing an error
503
+ // here. `'static` is too strict to be useful,
504
+ // most likely, and the resulting errors may
505
+ // well be rather confusing.
506
+ break ;
507
+ }
508
+ } else {
509
+ bound_region = Some ( subst_arg) ;
510
+ }
511
+ }
512
+ debug ! ( "constrain_anon_types: bound_region={:?}" , bound_region) ;
513
+
514
+ // If we don't find any arguments in the interface, then
515
+ // the only valid region that can appear in the resulting
516
+ // type is `'static`.
517
+ let bound_region = bound_region. unwrap_or ( self . tcx . types . re_static ) ;
518
+
519
+ // Require that all regions outlive `bound_region`
520
+ let span = self . tcx . def_span ( def_id) ;
521
+ self . tcx . for_each_free_region ( & concrete_ty, |region| {
522
+ self . sub_regions ( infer:: CallReturn ( span) , bound_region, region) ;
523
+ } ) ;
524
+ }
525
+ }
526
+
390
527
/// This method populates the region map's `free_region_map`. It walks over the transformed
391
528
/// argument and return types for each function just before we check the body of that function,
392
529
/// looking for types where you have a borrowed pointer to other borrowed data (e.g., `&'a &'b
0 commit comments