1
+ use crate::infer::outlives::components::{compute_components_recursive, Component};
1
2
use crate::infer::outlives::env::RegionBoundPairs;
2
3
use crate::infer::region_constraints::VerifyIfEq;
3
4
use crate::infer::{GenericKind, VerifyBound};
4
5
use rustc_data_structures::captures::Captures;
5
6
use rustc_data_structures::sso::SsoHashSet;
6
7
use rustc_hir::def_id::DefId;
7
- use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
8
+ use rustc_middle::ty::subst::{GenericArg, Subst};
8
9
use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt};
9
10
11
+ use smallvec::smallvec;
12
+
10
13
/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
11
14
/// obligation into a series of `'a: 'b` constraints and "verifys", as
12
15
/// described on the module comment. The final constraints are emitted
@@ -47,43 +50,6 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
47
50
}
48
51
}
49
52
50
- fn type_bound(
51
- &self,
52
- ty: Ty<'tcx>,
53
- visited: &mut SsoHashSet<GenericArg<'tcx>>,
54
- ) -> VerifyBound<'tcx> {
55
- match *ty.kind() {
56
- ty::Param(p) => self.param_bound(p),
57
- ty::Projection(data) => self.projection_bound(data, visited),
58
- ty::FnDef(_, substs) => {
59
- // HACK(eddyb) ignore lifetimes found shallowly in `substs`.
60
- // This is inconsistent with `ty::Adt` (including all substs),
61
- // but consistent with previous (accidental) behavior.
62
- // See https://github.com/rust-lang/rust/issues/70917
63
- // for further background and discussion.
64
- let mut bounds = substs
65
- .iter()
66
- .filter_map(|child| match child.unpack() {
67
- GenericArgKind::Type(ty) => Some(self.type_bound(ty, visited)),
68
- GenericArgKind::Lifetime(_) => None,
69
- GenericArgKind::Const(_) => Some(self.recursive_bound(child, visited)),
70
- })
71
- .filter(|bound| {
72
- // Remove bounds that must hold, since they are not interesting.
73
- !bound.must_hold()
74
- });
75
-
76
- match (bounds.next(), bounds.next()) {
77
- (Some(first), None) => first,
78
- (first, second) => VerifyBound::AllBounds(
79
- first.into_iter().chain(second).chain(bounds).collect(),
80
- ),
81
- }
82
- }
83
- _ => self.recursive_bound(ty.into(), visited),
84
- }
85
- }
86
-
87
53
fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
88
54
debug!("param_bound(param_ty={:?})", param_ty);
89
55
@@ -188,27 +154,24 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
188
154
.map(|r| VerifyBound::OutlivedBy(r));
189
155
190
156
// see the extensive comment in projection_must_outlive
191
- let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs);
192
- let recursive_bound = self.recursive_bound(ty.into(), visited);
157
+ let recursive_bound = {
158
+ let mut components = smallvec![];
159
+ let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs);
160
+ compute_components_recursive(self.tcx, ty.into(), &mut components, visited);
161
+ self.bound_from_components(&components, visited)
162
+ };
193
163
194
164
VerifyBound::AnyBound(env_bounds.chain(trait_bounds).collect()).or(recursive_bound)
195
165
}
196
166
197
- fn recursive_bound (
167
+ fn bound_from_components (
198
168
&self,
199
- parent: GenericArg <'tcx>,
169
+ components: &[Component <'tcx>] ,
200
170
visited: &mut SsoHashSet<GenericArg<'tcx>>,
201
171
) -> VerifyBound<'tcx> {
202
- let mut bounds = parent
203
- .walk_shallow(visited)
204
- .filter_map(|child| match child.unpack() {
205
- GenericArgKind::Type(ty) => Some(self.type_bound(ty, visited)),
206
- GenericArgKind::Lifetime(lt) => {
207
- // Ignore late-bound regions.
208
- if !lt.is_late_bound() { Some(VerifyBound::OutlivedBy(lt)) } else { None }
209
- }
210
- GenericArgKind::Const(_) => Some(self.recursive_bound(child, visited)),
211
- })
172
+ let mut bounds = components
173
+ .iter()
174
+ .map(|component| self.bound_from_single_component(component, visited))
212
175
.filter(|bound| {
213
176
// Remove bounds that must hold, since they are not interesting.
214
177
!bound.must_hold()
@@ -222,6 +185,32 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
222
185
}
223
186
}
224
187
188
+ fn bound_from_single_component(
189
+ &self,
190
+ component: &Component<'tcx>,
191
+ visited: &mut SsoHashSet<GenericArg<'tcx>>,
192
+ ) -> VerifyBound<'tcx> {
193
+ match *component {
194
+ Component::Region(lt) => VerifyBound::OutlivedBy(lt),
195
+ Component::Param(param_ty) => self.param_bound(param_ty),
196
+ Component::Projection(projection_ty) => self.projection_bound(projection_ty, visited),
197
+ Component::EscapingProjection(ref components) => {
198
+ self.bound_from_components(components, visited)
199
+ }
200
+ Component::UnresolvedInferenceVariable(v) => {
201
+ // ignore this, we presume it will yield an error
202
+ // later, since if a type variable is not resolved by
203
+ // this point it never will be
204
+ self.tcx.sess.delay_span_bug(
205
+ rustc_span::DUMMY_SP,
206
+ &format!("unresolved inference variable in outlives: {:?}", v),
207
+ );
208
+ // add a bound that never holds
209
+ VerifyBound::AnyBound(vec![])
210
+ }
211
+ }
212
+ }
213
+
225
214
/// Searches the environment for where-clauses like `G: 'a` where
226
215
/// `G` is either some type parameter `T` or a projection like
227
216
/// `T::Item`. Returns a vector of the `'a` bounds it can find.
0 commit comments