1 use rustc_middle
::ty
::outlives
::Component
;
2 use rustc_middle
::ty
::subst
::{GenericArg, GenericArgKind}
;
3 use rustc_middle
::ty
::{self, Region, RegionKind, Ty, TyCtxt}
;
5 use smallvec
::smallvec
;
6 use std
::collections
::BTreeMap
;
8 /// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred
9 /// must be added to the struct header.
10 pub type RequiredPredicates
<'tcx
> =
11 BTreeMap
<ty
::OutlivesPredicate
<GenericArg
<'tcx
>, ty
::Region
<'tcx
>>, Span
>;
13 /// Given a requirement `T: 'a` or `'b: 'a`, deduce the
14 /// outlives_component and add it to `required_predicates`
15 pub fn insert_outlives_predicate
<'tcx
>(
17 kind
: GenericArg
<'tcx
>,
18 outlived_region
: Region
<'tcx
>,
20 required_predicates
: &mut RequiredPredicates
<'tcx
>,
22 // If the `'a` region is bound within the field type itself, we
23 // don't want to propagate this constraint to the header.
24 if !is_free_region(tcx
, outlived_region
) {
29 GenericArgKind
::Type(ty
) => {
30 // `T: 'outlived_region` for some type `T`
31 // But T could be a lot of things:
32 // e.g., if `T = &'b u32`, then `'b: 'outlived_region` is
33 // what we want to add.
35 // Or if within `struct Foo<U>` you had `T = Vec<U>`, then
36 // we would want to add `U: 'outlived_region`
37 let mut components
= smallvec
![];
38 tcx
.push_outlives_components(ty
, &mut components
);
39 for component
in components
{
41 Component
::Region(r
) => {
42 // This would arise from something like:
45 // struct Foo<'a, 'b> {
50 // Here `outlived_region = 'a` and `kind = &'b
51 // u32`. Decomposing `&'b u32` into
52 // components would yield `'b`, and we add the
53 // where clause that `'b: 'a`.
54 insert_outlives_predicate(
63 Component
::Param(param_ty
) => {
64 // param_ty: ty::ParamTy
65 // This would arise from something like:
68 // struct Foo<'a, U> {
73 // Here `outlived_region = 'a` and `kind =
74 // Vec<U>`. Decomposing `Vec<U>` into
75 // components would yield `U`, and we add the
76 // where clause that `U: 'a`.
77 let ty
: Ty
<'tcx
> = param_ty
.to_ty(tcx
);
79 .entry(ty
::OutlivesPredicate(ty
.into(), outlived_region
))
83 Component
::Projection(proj_ty
) => {
84 // This would arise from something like:
87 // struct Foo<'a, T: Iterator> {
88 // x: &'a <T as Iterator>::Item
92 // Here we want to add an explicit `where <T as Iterator>::Item: 'a`.
93 let ty
: Ty
<'tcx
> = tcx
.mk_projection(proj_ty
.item_def_id
, proj_ty
.substs
);
95 .entry(ty
::OutlivesPredicate(ty
.into(), outlived_region
))
99 Component
::EscapingProjection(_
) => {
100 // As above, but the projection involves
101 // late-bound regions. Therefore, the WF
102 // requirement is not checked in type definition
103 // but at fn call site, so ignore it.
106 // struct Foo<'a, T: Iterator> {
107 // x: for<'b> fn(<&'b T as Iterator>::Item)
108 // // ^^^^^^^^^^^^^^^^^^^^^^^^^
112 // Since `'b` is not in scope on `Foo`, can't
113 // do anything here, ignore it.
116 Component
::UnresolvedInferenceVariable(_
) => bug
!("not using infcx"),
121 GenericArgKind
::Lifetime(r
) => {
122 if !is_free_region(tcx
, r
) {
125 required_predicates
.entry(ty
::OutlivesPredicate(kind
, outlived_region
)).or_insert(span
);
128 GenericArgKind
::Const(_
) => {
129 // Generic consts don't impose any constraints.
134 fn is_free_region(tcx
: TyCtxt
<'_
>, region
: Region
<'_
>) -> bool
{
135 // First, screen for regions that might appear in a type header.
137 // These correspond to `T: 'a` relationships:
139 // struct Foo<'a, T> {
140 // field: &'a T, // this would generate a ReEarlyBound referencing `'a`
143 // We care about these, so fall through.
144 RegionKind
::ReEarlyBound(_
) => true,
146 // These correspond to `T: 'static` relationships which can be
147 // rather surprising. We are therefore putting this behind a
150 // struct Foo<'a, T> {
151 // field: &'static T, // this would generate a ReStatic
153 RegionKind
::ReStatic
=> tcx
.sess
.features_untracked().infer_static_outlives_requirements
,
155 // Late-bound regions can appear in `fn` types:
158 // field: for<'b> fn(&'b T) // e.g., 'b here
161 // The type above might generate a `T: 'b` bound, but we can
162 // ignore it. We can't put it on the struct header anyway.
163 RegionKind
::ReLateBound(..) => false,
165 // This can appear in `where Self: ` bounds (#64855):
167 // struct Bar<T>(<Self as Foo>::Type) where Self: ;
168 // struct Baz<'a>(&'a Self) where Self: ;
169 RegionKind
::ReEmpty(_
) => false,
171 // These regions don't appear in types from type declarations:
173 | RegionKind
::ReScope(..)
174 | RegionKind
::ReVar(..)
175 | RegionKind
::RePlaceholder(..)
176 | RegionKind
::ReFree(..) => {
177 bug
!("unexpected region in outlives inference: {:?}", region
);