@@ -13,27 +13,27 @@ use crate::util::nodemap::DefIdMap;
13
13
14
14
pub type OpaqueTypeMap < ' tcx > = DefIdMap < OpaqueTypeDecl < ' tcx > > ;
15
15
16
- /// Information about the opaque, abstract types whose values we
16
+ /// Information about the opaque, existential types whose values we
17
17
/// are inferring in this function (these are the `impl Trait` that
18
18
/// appear in the return type).
19
19
#[ derive( Copy , Clone , Debug ) ]
20
20
pub struct OpaqueTypeDecl < ' tcx > {
21
- /// The substitutions that we apply to the abstract that this
21
+ /// The substitutions that we apply to the existential type that this
22
22
/// `impl Trait` desugars to. e.g., if:
23
23
///
24
24
/// fn foo<'a, 'b, T>() -> impl Trait<'a>
25
25
///
26
26
/// winds up desugared to:
27
27
///
28
- /// abstract type Foo<'x, X>: Trait<'x>
28
+ /// existential type Foo<'x, X>: Trait<'x>
29
29
/// fn foo<'a, 'b, T>() -> Foo<'a, T>
30
30
///
31
31
/// then `substs` would be `['a, T]`.
32
32
pub substs : SubstsRef < ' tcx > ,
33
33
34
- /// The type variable that represents the value of the abstract type
34
+ /// The type variable that represents the value of the existential type
35
35
/// that we require. In other words, after we compile this function,
36
- /// we will be created a constraint like:
36
+ /// we will have created a constraint like:
37
37
///
38
38
/// Foo<'a, T> = ?C
39
39
///
@@ -141,12 +141,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
141
141
/// Here, we have two `impl Trait` types whose values are being
142
142
/// inferred (the `impl Bar<'a>` and the `impl
143
143
/// Bar<'b>`). Conceptually, this is sugar for a setup where we
144
- /// define underlying abstract types (`Foo1`, `Foo2`) and then, in
144
+ /// define underlying existential types (`Foo1`, `Foo2`) and then, in
145
145
/// the return type of `foo`, we *reference* those definitions:
146
146
///
147
147
/// ```text
148
- /// abstract type Foo1<'x>: Bar<'x>;
149
- /// abstract type Foo2<'x>: Bar<'x>;
148
+ /// existential type Foo1<'x>: Bar<'x>;
149
+ /// existential type Foo2<'x>: Bar<'x>;
150
150
/// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
151
151
/// // ^^^^ ^^
152
152
/// // | |
@@ -205,7 +205,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
205
205
///
206
206
/// This is actually a bit of a tricky constraint in general. We
207
207
/// want to say that each variable (e.g., `'0`) can only take on
208
- /// values that were supplied as arguments to the abstract type
208
+ /// values that were supplied as arguments to the existential type
209
209
/// (e.g., `'a` for `Foo1<'a>`) or `'static`, which is always in
210
210
/// scope. We don't have a constraint quite of this kind in the current
211
211
/// region checker.
@@ -232,10 +232,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
232
232
/// # The `free_region_relations` parameter
233
233
///
234
234
/// The `free_region_relations` argument is used to find the
235
- /// "minimum" of the regions supplied to a given abstract type.
235
+ /// "minimum" of the regions supplied to a given existential type.
236
236
/// It must be a relation that can answer whether `'a <= 'b`,
237
237
/// where `'a` and `'b` are regions that appear in the "substs"
238
- /// for the abstract type references (the `<'a>` in `Foo1<'a>`).
238
+ /// for the existential type references (the `<'a>` in `Foo1<'a>`).
239
239
///
240
240
/// Note that we do not impose the constraints based on the
241
241
/// generic regions from the `Foo1` definition (e.g., `'x`). This
@@ -251,7 +251,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
251
251
///
252
252
/// Here, the fact that `'b: 'a` is known only because of the
253
253
/// implied bounds from the `&'a &'b u32` parameter, and is not
254
- /// "inherent" to the abstract type definition.
254
+ /// "inherent" to the existential type definition.
255
255
///
256
256
/// # Parameters
257
257
///
@@ -364,16 +364,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
364
364
}
365
365
366
366
Component :: Param ( _) => {
367
- // ignore type parameters like `T`, they are captured
368
- // implicitly by the `impl Trait`
367
+ // Ignore type parameters like `T`, since they are captured
368
+ // implicitly by the `impl Trait`.
369
369
}
370
370
371
371
Component :: UnresolvedInferenceVariable ( _) => {
372
- // we should get an error that more type
373
- // annotations are needed in this case
372
+ // We should get an error that more type
373
+ // annotations are needed in this case.
374
374
self . tcx
375
375
. sess
376
- . delay_span_bug ( span, "unresolved inf var in opaque" ) ;
376
+ . delay_span_bug ( span, "unresolved inf var in opaque type " ) ;
377
377
}
378
378
379
379
Component :: Projection ( ty:: ProjectionTy {
@@ -397,20 +397,32 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
397
397
}
398
398
}
399
399
}
400
+
401
+ // For soundness, we need to ensure that every region that is captured by the opaque type
402
+ // but does not explicitly appear in the opaque type outlives the actual (concrete) type.
403
+ // This allows for invariant lifetimes to be captured by opaque types as long as
404
+ // short-lived lifetimes are not permitted to escape and cause UB.
405
+ let opaque_substs_regions = opaque_defn. substs . regions ( ) . collect ( ) ;
406
+ let captured_regions = concrete_ty_regions. difference ( & opaque_substs_regions) ;
407
+ for captured_region in captured_regions {
408
+ for concrete_ty_region in & concrete_ty_regions {
409
+ self . sub_regions ( infer:: CallReturn ( span) , * concrete_ty_region, captured_region)
410
+ }
411
+ }
400
412
}
401
413
402
414
/// Given the fully resolved, instantiated type for an opaque
403
415
/// type, i.e., the value of an inference variable like C1 or C2
404
- /// (*), computes the "definition type" for an abstract type
416
+ /// (*), computes the "definition type" for an existential type
405
417
/// definition -- that is, the inferred value of `Foo1<'x>` or
406
418
/// `Foo2<'x>` that we would conceptually use in its definition:
407
419
///
408
- /// abstract type Foo1<'x>: Bar<'x> = AAA; <-- this type AAA
409
- /// abstract type Foo2<'x>: Bar<'x> = BBB; <-- or this type BBB
420
+ /// existential type Foo1<'x>: Bar<'x> = AAA; <-- this type AAA
421
+ /// existential type Foo2<'x>: Bar<'x> = BBB; <-- or this type BBB
410
422
/// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
411
423
///
412
- /// Note that these values are defined in terms of a distinct set of
413
- /// generic parameters (`'x` instead of `'a`) from C1 or C2. The main
424
+ /// Note that these values are defined in terms of a set of generic
425
+ /// parameters (`'x` instead of `'a`) distinct from C1 and C2. The main
414
426
/// purpose of this function is to do that translation.
415
427
///
416
428
/// (*) C1 and C2 were introduced in the comments on
@@ -450,23 +462,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
450
462
. collect ( ) ;
451
463
452
464
// Convert the type from the function into a type valid outside
453
- // the function, by replacing invalid regions with 'static,
465
+ // the function, by replacing invalid regions with ` 'static` ,
454
466
// after producing an error for each of them.
455
467
let definition_ty =
456
- instantiated_ty. fold_with ( & mut ReverseMapper :: new (
457
- self . tcx ,
458
- self . is_tainted_by_errors ( ) ,
459
- def_id,
468
+ instantiated_ty. fold_with ( & mut ReverseMapper {
469
+ tcx : self . tcx ,
460
470
map,
461
- instantiated_ty,
462
- ) ) ;
471
+ } ) ;
463
472
debug ! (
464
473
"infer_opaque_definition_from_instantiation: definition_ty={:?}" ,
465
474
definition_ty
466
475
) ;
467
476
468
477
// We can unwrap here because our reverse mapper always
469
- // produces things with 'gcx lifetime, though the type folder
478
+ // produces things with ` 'gcx` lifetime, though the type folder
470
479
// obscures that.
471
480
let definition_ty = gcx. lift ( & definition_ty) . unwrap ( ) ;
472
481
@@ -656,20 +665,20 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
656
665
// value we are inferring. At present, this is
657
666
// always true during the first phase of
658
667
// type-check, but not always true later on during
659
- // NLL. Once we support named abstract types more fully,
668
+ // NLL. Once we support named existential types more fully,
660
669
// this same scenario will be able to arise during all phases.
661
670
//
662
- // Here is an example using `abstract type` that indicates
671
+ // Here is an example using `existential type` that indicates
663
672
// the distinction we are checking for:
664
673
//
665
674
// ```rust
666
675
// mod a {
667
- // pub abstract type Foo: Iterator;
668
- // pub fn make_foo() -> Foo { .. }
676
+ // pub existential type Foo: Iterator;
677
+ // pub fn make_foo() -> Foo { .. }
669
678
// }
670
679
//
671
680
// mod b {
672
- // fn foo() -> a::Foo { a::make_foo() }
681
+ // fn foo() -> a::Foo { a::make_foo() }
673
682
// }
674
683
// ```
675
684
//
@@ -777,7 +786,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
777
786
required_region_bounds
778
787
) ;
779
788
780
- // make sure that we are in fact defining the *entire* type
789
+ // Make sure that we are in fact defining the *entire* type
781
790
// e.g., `existential type Foo<T: Bound>: Bar;` needs to be
782
791
// defined by a function like `fn foo<T: Bound>() -> Foo<T>`.
783
792
debug ! (
0 commit comments