]>
Commit | Line | Data |
---|---|---|
9fa01778 | 1 | use crate::infer::InferCtxt; |
ba9703b0 | 2 | use crate::traits; |
dfeec247 | 3 | use rustc_hir as hir; |
3dfed10e | 4 | use rustc_hir::lang_items::LangItem; |
f035d41b | 5 | use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; |
9ffffee4 FG |
6 | use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; |
7 | use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; | |
8 | use rustc_span::{Span, DUMMY_SP}; | |
e9174d1e | 9 | |
1b1a35ee | 10 | use std::iter; |
f035d41b XL |
11 | /// Returns the set of obligations needed to make `arg` well-formed. |
12 | /// If `arg` contains unresolved inference variables, this may include | |
13 | /// further WF obligations. However, if `arg` IS an unresolved | |
e9174d1e SL |
14 | /// inference variable, returns `None`, because we are not able to |
15 | /// make any progress at all. This is to prevent "livelock" where we | |
16 | /// say "$0 is WF if $0 is WF". | |
2b03887a FG |
17 | pub fn obligations<'tcx>( |
18 | infcx: &InferCtxt<'tcx>, | |
dc9dc135 | 19 | param_env: ty::ParamEnv<'tcx>, |
9ffffee4 | 20 | body_id: LocalDefId, |
29967ef6 | 21 | recursion_depth: usize, |
f035d41b | 22 | arg: GenericArg<'tcx>, |
dc9dc135 XL |
23 | span: Span, |
24 | ) -> Option<Vec<traits::PredicateObligation<'tcx>>> { | |
f9f354fc | 25 | // Handle the "livelock" case (see comment above) by bailing out if necessary. |
f035d41b XL |
26 | let arg = match arg.unpack() { |
27 | GenericArgKind::Type(ty) => { | |
1b1a35ee | 28 | match ty.kind() { |
f035d41b XL |
29 | ty::Infer(ty::TyVar(_)) => { |
30 | let resolved_ty = infcx.shallow_resolve(ty); | |
31 | if resolved_ty == ty { | |
32 | // No progress, bail out to prevent "livelock". | |
33 | return None; | |
f2b60f7d FG |
34 | } else { |
35 | resolved_ty | |
f035d41b | 36 | } |
f035d41b XL |
37 | } |
38 | _ => ty, | |
f9f354fc | 39 | } |
f035d41b XL |
40 | .into() |
41 | } | |
42 | GenericArgKind::Const(ct) => { | |
923072b8 | 43 | match ct.kind() { |
f2b60f7d FG |
44 | ty::ConstKind::Infer(_) => { |
45 | let resolved = infcx.shallow_resolve(ct); | |
46 | if resolved == ct { | |
f035d41b XL |
47 | // No progress. |
48 | return None; | |
f2b60f7d FG |
49 | } else { |
50 | resolved | |
f035d41b | 51 | } |
f035d41b XL |
52 | } |
53 | _ => ct, | |
54 | } | |
55 | .into() | |
f9f354fc | 56 | } |
f035d41b XL |
57 | // There is nothing we have to do for lifetimes. |
58 | GenericArgKind::Lifetime(..) => return Some(Vec::new()), | |
f9f354fc XL |
59 | }; |
60 | ||
49aad941 FG |
61 | let mut wf = |
62 | WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth, item: None }; | |
f035d41b XL |
63 | wf.compute(arg); |
64 | debug!("wf::obligations({:?}, body_id={:?}) = {:?}", arg, body_id, wf.out); | |
f9f354fc | 65 | |
064997fb | 66 | let result = wf.normalize(infcx); |
f035d41b | 67 | debug!("wf::obligations({:?}, body_id={:?}) ~~> {:?}", arg, body_id, result); |
f9f354fc | 68 | Some(result) |
e9174d1e SL |
69 | } |
70 | ||
9ffffee4 FG |
71 | /// Compute the predicates that are required for a type to be well-formed. |
72 | /// | |
73 | /// This is only intended to be used in the new solver, since it does not | |
74 | /// take into account recursion depth or proper error-reporting spans. | |
75 | pub fn unnormalized_obligations<'tcx>( | |
76 | infcx: &InferCtxt<'tcx>, | |
77 | param_env: ty::ParamEnv<'tcx>, | |
78 | arg: GenericArg<'tcx>, | |
79 | ) -> Option<Vec<traits::PredicateObligation<'tcx>>> { | |
80 | if let ty::GenericArgKind::Lifetime(..) = arg.unpack() { | |
81 | return Some(vec![]); | |
82 | } | |
83 | ||
84 | debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg)); | |
85 | ||
86 | let mut wf = WfPredicates { | |
49aad941 | 87 | infcx, |
9ffffee4 FG |
88 | param_env, |
89 | body_id: CRATE_DEF_ID, | |
90 | span: DUMMY_SP, | |
91 | out: vec![], | |
92 | recursion_depth: 0, | |
93 | item: None, | |
94 | }; | |
95 | wf.compute(arg); | |
96 | Some(wf.out) | |
97 | } | |
98 | ||
e9174d1e | 99 | /// Returns the obligations that make this trait reference |
9c376795 | 100 | /// well-formed. For example, if there is a trait `Set` defined like |
e9174d1e SL |
101 | /// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF |
102 | /// if `Bar: Eq`. | |
2b03887a FG |
103 | pub fn trait_obligations<'tcx>( |
104 | infcx: &InferCtxt<'tcx>, | |
dc9dc135 | 105 | param_env: ty::ParamEnv<'tcx>, |
9ffffee4 | 106 | body_id: LocalDefId, |
064997fb | 107 | trait_pred: &ty::TraitPredicate<'tcx>, |
dc9dc135 | 108 | span: Span, |
923072b8 | 109 | item: &'tcx hir::Item<'tcx>, |
dc9dc135 | 110 | ) -> Vec<traits::PredicateObligation<'tcx>> { |
923072b8 | 111 | let mut wf = WfPredicates { |
49aad941 | 112 | infcx, |
923072b8 FG |
113 | param_env, |
114 | body_id, | |
115 | span, | |
116 | out: vec![], | |
117 | recursion_depth: 0, | |
118 | item: Some(item), | |
119 | }; | |
064997fb | 120 | wf.compute_trait_pred(trait_pred, Elaborate::All); |
136023e0 | 121 | debug!(obligations = ?wf.out); |
064997fb | 122 | wf.normalize(infcx) |
e9174d1e SL |
123 | } |
124 | ||
f2b60f7d | 125 | #[instrument(skip(infcx), ret)] |
2b03887a FG |
126 | pub fn predicate_obligations<'tcx>( |
127 | infcx: &InferCtxt<'tcx>, | |
dc9dc135 | 128 | param_env: ty::ParamEnv<'tcx>, |
9ffffee4 | 129 | body_id: LocalDefId, |
f9f354fc | 130 | predicate: ty::Predicate<'tcx>, |
dc9dc135 XL |
131 | span: Span, |
132 | ) -> Vec<traits::PredicateObligation<'tcx>> { | |
29967ef6 | 133 | let mut wf = WfPredicates { |
49aad941 | 134 | infcx, |
29967ef6 XL |
135 | param_env, |
136 | body_id, | |
137 | span, | |
138 | out: vec![], | |
139 | recursion_depth: 0, | |
140 | item: None, | |
141 | }; | |
e9174d1e | 142 | |
3dfed10e | 143 | // It's ok to skip the binder here because wf code is prepared for it |
5869c6ff | 144 | match predicate.kind().skip_binder() { |
487cf647 | 145 | ty::PredicateKind::Clause(ty::Clause::Trait(t)) => { |
064997fb | 146 | wf.compute_trait_pred(&t, Elaborate::None); |
e9174d1e | 147 | } |
487cf647 FG |
148 | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) => {} |
149 | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(ty, _reg))) => { | |
3dfed10e | 150 | wf.compute(ty.into()); |
e9174d1e | 151 | } |
487cf647 | 152 | ty::PredicateKind::Clause(ty::Clause::Projection(t)) => { |
e9174d1e | 153 | wf.compute_projection(t.projection_ty); |
f2b60f7d FG |
154 | wf.compute(match t.term.unpack() { |
155 | ty::TermKind::Ty(ty) => ty.into(), | |
156 | ty::TermKind::Const(c) => c.into(), | |
5099ac24 | 157 | }) |
e9174d1e | 158 | } |
9ffffee4 FG |
159 | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { |
160 | wf.compute(ct.into()); | |
161 | wf.compute(ty.into()); | |
162 | } | |
5869c6ff | 163 | ty::PredicateKind::WellFormed(arg) => { |
f035d41b | 164 | wf.compute(arg); |
e9174d1e | 165 | } |
49aad941 | 166 | |
2b03887a FG |
167 | ty::PredicateKind::ConstEvaluatable(ct) => { |
168 | wf.compute(ct.into()); | |
ea8adc8c | 169 | } |
49aad941 FG |
170 | |
171 | ty::PredicateKind::ObjectSafe(_) | |
172 | | ty::PredicateKind::ClosureKind(..) | |
173 | | ty::PredicateKind::Subtype(..) | |
174 | | ty::PredicateKind::Coerce(..) | |
175 | | ty::PredicateKind::ConstEquate(..) | |
176 | | ty::PredicateKind::Ambiguous | |
177 | | ty::PredicateKind::AliasRelate(..) | |
178 | | ty::PredicateKind::TypeWellFormedFromEnv(..) => { | |
179 | bug!("We should only wf check where clauses, unexpected predicate: {predicate:?}") | |
9ffffee4 | 180 | } |
e9174d1e SL |
181 | } |
182 | ||
064997fb | 183 | wf.normalize(infcx) |
e9174d1e SL |
184 | } |
185 | ||
49aad941 FG |
186 | struct WfPredicates<'a, 'tcx> { |
187 | infcx: &'a InferCtxt<'tcx>, | |
7cac9316 | 188 | param_env: ty::ParamEnv<'tcx>, |
9ffffee4 | 189 | body_id: LocalDefId, |
e9174d1e SL |
190 | span: Span, |
191 | out: Vec<traits::PredicateObligation<'tcx>>, | |
29967ef6 | 192 | recursion_depth: usize, |
dfeec247 | 193 | item: Option<&'tcx hir::Item<'tcx>>, |
e9174d1e SL |
194 | } |
195 | ||
3b2f2976 XL |
196 | /// Controls whether we "elaborate" supertraits and so forth on the WF |
197 | /// predicates. This is a kind of hack to address #43784. The | |
198 | /// underlying problem in that issue was a trait structure like: | |
199 | /// | |
04454e1e | 200 | /// ```ignore (illustrative) |
3b2f2976 XL |
201 | /// trait Foo: Copy { } |
202 | /// trait Bar: Foo { } | |
203 | /// impl<T: Bar> Foo for T { } | |
204 | /// impl<T> Bar for T { } | |
205 | /// ``` | |
206 | /// | |
207 | /// Here, in the `Foo` impl, we will check that `T: Copy` holds -- but | |
208 | /// we decide that this is true because `T: Bar` is in the | |
209 | /// where-clauses (and we can elaborate that to include `T: | |
210 | /// Copy`). This wouldn't be a problem, except that when we check the | |
211 | /// `Bar` impl, we decide that `T: Foo` must hold because of the `Foo` | |
212 | /// impl. And so nowhere did we check that `T: Copy` holds! | |
213 | /// | |
214 | /// To resolve this, we elaborate the WF requirements that must be | |
215 | /// proven when checking impls. This means that (e.g.) the `impl Bar | |
216 | /// for T` will be forced to prove not only that `T: Foo` but also `T: | |
217 | /// Copy` (which it won't be able to do, because there is no `Copy` | |
218 | /// impl for `T`). | |
219 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] | |
220 | enum Elaborate { | |
221 | All, | |
222 | None, | |
223 | } | |
224 | ||
ba9703b0 XL |
225 | fn extend_cause_with_original_assoc_item_obligation<'tcx>( |
226 | tcx: TyCtxt<'tcx>, | |
227 | trait_ref: &ty::TraitRef<'tcx>, | |
228 | item: Option<&hir::Item<'tcx>>, | |
229 | cause: &mut traits::ObligationCause<'tcx>, | |
5099ac24 | 230 | pred: ty::Predicate<'tcx>, |
ba9703b0 XL |
231 | ) { |
232 | debug!( | |
233 | "extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}", | |
234 | trait_ref, item, cause, pred | |
235 | ); | |
5099ac24 | 236 | let (items, impl_def_id) = match item { |
2b03887a FG |
237 | Some(hir::Item { kind: hir::ItemKind::Impl(impl_), owner_id, .. }) => { |
238 | (impl_.items, *owner_id) | |
239 | } | |
ba9703b0 XL |
240 | _ => return, |
241 | }; | |
242 | let fix_span = | |
c295e0f8 | 243 | |impl_item_ref: &hir::ImplItemRef| match tcx.hir().impl_item(impl_item_ref.id).kind { |
2b03887a | 244 | hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::Type(ty) => ty.span, |
ba9703b0 XL |
245 | _ => impl_item_ref.span, |
246 | }; | |
3dfed10e XL |
247 | |
248 | // It is fine to skip the binder as we don't care about regions here. | |
5869c6ff | 249 | match pred.kind().skip_binder() { |
487cf647 | 250 | ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => { |
f9f354fc XL |
251 | // The obligation comes not from the current `impl` nor the `trait` being implemented, |
252 | // but rather from a "second order" obligation, where an associated type has a | |
253 | // projection coming from another associated type. See | |
9c376795 | 254 | // `tests/ui/associated-types/point-at-type-on-obligation-failure.rs` and |
f9f354fc | 255 | // `traits-assoc-type-in-supertrait-bad.rs`. |
9c376795 | 256 | if let Some(ty::Alias(ty::Projection, projection_ty)) = proj.term.ty().map(|ty| ty.kind()) |
5e7ed085 | 257 | && let Some(&impl_item_id) = |
9c376795 | 258 | tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.def_id) |
5e7ed085 FG |
259 | && let Some(impl_item_span) = items |
260 | .iter() | |
2b03887a | 261 | .find(|item| item.id.owner_id.to_def_id() == impl_item_id) |
5e7ed085 FG |
262 | .map(fix_span) |
263 | { | |
264 | cause.span = impl_item_span; | |
ba9703b0 XL |
265 | } |
266 | } | |
487cf647 | 267 | ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => { |
ba9703b0 XL |
268 | // An associated item obligation born out of the `trait` failed to be met. An example |
269 | // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`. | |
270 | debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred); | |
9c376795 | 271 | if let ty::Alias(ty::Projection, ty::AliasTy { def_id, .. }) = *pred.self_ty().kind() |
5e7ed085 | 272 | && let Some(&impl_item_id) = |
9c376795 | 273 | tcx.impl_item_implementor_ids(impl_def_id).get(&def_id) |
5e7ed085 FG |
274 | && let Some(impl_item_span) = items |
275 | .iter() | |
2b03887a | 276 | .find(|item| item.id.owner_id.to_def_id() == impl_item_id) |
5e7ed085 FG |
277 | .map(fix_span) |
278 | { | |
279 | cause.span = impl_item_span; | |
ba9703b0 XL |
280 | } |
281 | } | |
282 | _ => {} | |
283 | } | |
284 | } | |
285 | ||
49aad941 | 286 | impl<'a, 'tcx> WfPredicates<'a, 'tcx> { |
f9f354fc | 287 | fn tcx(&self) -> TyCtxt<'tcx> { |
49aad941 | 288 | self.infcx.tcx |
f9f354fc XL |
289 | } |
290 | ||
f035d41b | 291 | fn cause(&self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> { |
9cc50fc6 | 292 | traits::ObligationCause::new(self.span, self.body_id, code) |
e9174d1e SL |
293 | } |
294 | ||
2b03887a | 295 | fn normalize(self, infcx: &InferCtxt<'tcx>) -> Vec<traits::PredicateObligation<'tcx>> { |
064997fb | 296 | let cause = self.cause(traits::WellFormed(None)); |
7cac9316 | 297 | let param_env = self.param_env; |
74b04a01 | 298 | let mut obligations = Vec::with_capacity(self.out.len()); |
29967ef6 XL |
299 | for mut obligation in self.out { |
300 | assert!(!obligation.has_escaping_bound_vars()); | |
74b04a01 | 301 | let mut selcx = traits::SelectionContext::new(infcx); |
29967ef6 XL |
302 | // Don't normalize the whole obligation, the param env is either |
303 | // already normalized, or we're currently normalizing the | |
304 | // param_env. Either way we should only normalize the predicate. | |
305 | let normalized_predicate = traits::project::normalize_with_depth_to( | |
306 | &mut selcx, | |
307 | param_env, | |
308 | cause.clone(), | |
309 | self.recursion_depth, | |
fc512014 | 310 | obligation.predicate, |
29967ef6 XL |
311 | &mut obligations, |
312 | ); | |
313 | obligation.predicate = normalized_predicate; | |
314 | obligations.push(obligation); | |
74b04a01 XL |
315 | } |
316 | obligations | |
e9174d1e SL |
317 | } |
318 | ||
e74abb32 | 319 | /// Pushes the obligations required for `trait_ref` to be WF into `self.out`. |
064997fb | 320 | fn compute_trait_pred(&mut self, trait_pred: &ty::TraitPredicate<'tcx>, elaborate: Elaborate) { |
49aad941 | 321 | let tcx = self.tcx(); |
064997fb | 322 | let trait_ref = &trait_pred.trait_ref; |
e9174d1e | 323 | |
49aad941 FG |
324 | // Negative trait predicates don't require supertraits to hold, just |
325 | // that their substs are WF. | |
326 | if trait_pred.polarity == ty::ImplPolarity::Negative { | |
327 | self.compute_negative_trait_pred(trait_ref); | |
328 | return; | |
329 | } | |
330 | ||
064997fb FG |
331 | // if the trait predicate is not const, the wf obligations should not be const as well. |
332 | let obligations = if trait_pred.constness == ty::BoundConstness::NotConst { | |
333 | self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.substs) | |
334 | } else { | |
335 | self.nominal_obligations(trait_ref.def_id, trait_ref.substs) | |
336 | }; | |
337 | ||
338 | debug!("compute_trait_pred obligations {:?}", obligations); | |
7cac9316 | 339 | let param_env = self.param_env; |
29967ef6 | 340 | let depth = self.recursion_depth; |
3b2f2976 | 341 | |
ba9703b0 | 342 | let item = self.item; |
dfeec247 | 343 | |
923072b8 FG |
344 | let extend = |traits::PredicateObligation { predicate, mut cause, .. }| { |
345 | if let Some(parent_trait_pred) = predicate.to_opt_poly_trait_pred() { | |
346 | cause = cause.derived_cause( | |
5099ac24 | 347 | parent_trait_pred, |
923072b8 FG |
348 | traits::ObligationCauseCode::DerivedObligation, |
349 | ); | |
ba9703b0 XL |
350 | } |
351 | extend_cause_with_original_assoc_item_obligation( | |
923072b8 | 352 | tcx, trait_ref, item, &mut cause, predicate, |
ba9703b0 | 353 | ); |
487cf647 | 354 | traits::Obligation::with_depth(tcx, cause, depth, param_env, predicate) |
ba9703b0 | 355 | }; |
e74abb32 | 356 | |
3b2f2976 | 357 | if let Elaborate::All = elaborate { |
353b0b11 | 358 | let implied_obligations = traits::util::elaborate(tcx, obligations); |
ba9703b0 | 359 | let implied_obligations = implied_obligations.map(extend); |
3b2f2976 | 360 | self.out.extend(implied_obligations); |
ba9703b0 XL |
361 | } else { |
362 | self.out.extend(obligations); | |
3b2f2976 XL |
363 | } |
364 | ||
f035d41b XL |
365 | self.out.extend( |
366 | trait_ref | |
367 | .substs | |
368 | .iter() | |
3dfed10e XL |
369 | .enumerate() |
370 | .filter(|(_, arg)| { | |
f035d41b XL |
371 | matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..)) |
372 | }) | |
3dfed10e XL |
373 | .filter(|(_, arg)| !arg.has_escaping_bound_vars()) |
374 | .map(|(i, arg)| { | |
923072b8 | 375 | let mut cause = traits::ObligationCause::misc(self.span, self.body_id); |
3dfed10e XL |
376 | // The first subst is the self ty - use the correct span for it. |
377 | if i == 0 { | |
5869c6ff XL |
378 | if let Some(hir::ItemKind::Impl(hir::Impl { self_ty, .. })) = |
379 | item.map(|i| &i.kind) | |
380 | { | |
923072b8 | 381 | cause.span = self_ty.span; |
3dfed10e XL |
382 | } |
383 | } | |
29967ef6 | 384 | traits::Obligation::with_depth( |
487cf647 | 385 | tcx, |
923072b8 | 386 | cause, |
29967ef6 | 387 | depth, |
f035d41b | 388 | param_env, |
487cf647 | 389 | ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)), |
f035d41b XL |
390 | ) |
391 | }), | |
392 | ); | |
e9174d1e SL |
393 | } |
394 | ||
49aad941 FG |
395 | // Compute the obligations that are required for `trait_ref` to be WF, |
396 | // given that it is a *negative* trait predicate. | |
397 | fn compute_negative_trait_pred(&mut self, trait_ref: &ty::TraitRef<'tcx>) { | |
398 | for arg in trait_ref.substs { | |
399 | self.compute(arg); | |
400 | } | |
401 | } | |
402 | ||
e9174d1e SL |
403 | /// Pushes the obligations required for `trait_ref::Item` to be WF |
404 | /// into `self.out`. | |
9c376795 | 405 | fn compute_projection(&mut self, data: ty::AliasTy<'tcx>) { |
29967ef6 XL |
406 | // A projection is well-formed if |
407 | // | |
408 | // (a) its predicates hold (*) | |
409 | // (b) its substs are wf | |
410 | // | |
411 | // (*) The predicates of an associated type include the predicates of | |
412 | // the trait that it's contained in. For example, given | |
413 | // | |
414 | // trait A<T>: Clone { | |
415 | // type X where T: Copy; | |
416 | // } | |
417 | // | |
418 | // The predicates of `<() as A<i32>>::X` are: | |
419 | // [ | |
420 | // `(): Sized` | |
421 | // `(): Clone` | |
422 | // `(): A<i32>` | |
423 | // `i32: Sized` | |
424 | // `i32: Clone` | |
425 | // `i32: Copy` | |
426 | // ] | |
2b03887a | 427 | // Projection types do not require const predicates. |
9c376795 | 428 | let obligations = self.nominal_obligations_without_const(data.def_id, data.substs); |
29967ef6 XL |
429 | self.out.extend(obligations); |
430 | ||
49aad941 FG |
431 | self.compute_projection_substs(data.substs); |
432 | } | |
433 | ||
434 | fn compute_inherent_projection(&mut self, data: ty::AliasTy<'tcx>) { | |
435 | // An inherent projection is well-formed if | |
436 | // | |
437 | // (a) its predicates hold (*) | |
438 | // (b) its substs are wf | |
439 | // | |
440 | // (*) The predicates of an inherent associated type include the | |
441 | // predicates of the impl that it's contained in. | |
442 | ||
443 | if !data.self_ty().has_escaping_bound_vars() { | |
444 | // FIXME(inherent_associated_types): Should this happen inside of a snapshot? | |
445 | // FIXME(inherent_associated_types): This is incompatible with the new solver and lazy norm! | |
446 | let substs = traits::project::compute_inherent_assoc_ty_substs( | |
447 | &mut traits::SelectionContext::new(self.infcx), | |
448 | self.param_env, | |
449 | data, | |
450 | self.cause(traits::WellFormed(None)), | |
451 | self.recursion_depth, | |
452 | &mut self.out, | |
453 | ); | |
454 | // Inherent projection types do not require const predicates. | |
455 | let obligations = self.nominal_obligations_without_const(data.def_id, substs); | |
456 | self.out.extend(obligations); | |
457 | } | |
458 | ||
459 | self.compute_projection_substs(data.substs); | |
460 | } | |
461 | ||
462 | fn compute_projection_substs(&mut self, substs: SubstsRef<'tcx>) { | |
29967ef6 | 463 | let tcx = self.tcx(); |
064997fb | 464 | let cause = self.cause(traits::WellFormed(None)); |
29967ef6 XL |
465 | let param_env = self.param_env; |
466 | let depth = self.recursion_depth; | |
467 | ||
468 | self.out.extend( | |
49aad941 | 469 | substs |
29967ef6 XL |
470 | .iter() |
471 | .filter(|arg| { | |
472 | matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..)) | |
473 | }) | |
474 | .filter(|arg| !arg.has_escaping_bound_vars()) | |
475 | .map(|arg| { | |
476 | traits::Obligation::with_depth( | |
487cf647 | 477 | tcx, |
29967ef6 XL |
478 | cause.clone(), |
479 | depth, | |
480 | param_env, | |
487cf647 | 481 | ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)), |
29967ef6 XL |
482 | ) |
483 | }), | |
484 | ); | |
e9174d1e SL |
485 | } |
486 | ||
9e0c209e | 487 | fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) { |
a1dfa0c6 | 488 | if !subty.has_escaping_bound_vars() { |
a7813a04 | 489 | let cause = self.cause(cause); |
49aad941 FG |
490 | let trait_ref = |
491 | ty::TraitRef::from_lang_item(self.tcx(), LangItem::Sized, cause.span, [subty]); | |
29967ef6 | 492 | self.out.push(traits::Obligation::with_depth( |
49aad941 | 493 | self.tcx(), |
dfeec247 | 494 | cause, |
29967ef6 | 495 | self.recursion_depth, |
dfeec247 | 496 | self.param_env, |
487cf647 | 497 | ty::Binder::dummy(trait_ref).without_const(), |
dfeec247 | 498 | )); |
a7813a04 XL |
499 | } |
500 | } | |
501 | ||
f9f354fc | 502 | /// Pushes all the predicates needed to validate that `ty` is WF into `out`. |
f2b60f7d | 503 | #[instrument(level = "debug", skip(self))] |
f035d41b | 504 | fn compute(&mut self, arg: GenericArg<'tcx>) { |
5099ac24 | 505 | let mut walker = arg.walk(); |
7cac9316 | 506 | let param_env = self.param_env; |
29967ef6 | 507 | let depth = self.recursion_depth; |
ba9703b0 | 508 | while let Some(arg) = walker.next() { |
f2b60f7d | 509 | debug!(?arg, ?self.out); |
ba9703b0 XL |
510 | let ty = match arg.unpack() { |
511 | GenericArgKind::Type(ty) => ty, | |
512 | ||
513 | // No WF constraints for lifetimes being present, any outlives | |
514 | // obligations are handled by the parent (e.g. `ty::Ref`). | |
515 | GenericArgKind::Lifetime(_) => continue, | |
516 | ||
2b03887a FG |
517 | GenericArgKind::Const(ct) => { |
518 | match ct.kind() { | |
94222f64 | 519 | ty::ConstKind::Unevaluated(uv) => { |
9c376795 | 520 | if !ct.has_escaping_bound_vars() { |
49aad941 | 521 | let obligations = self.nominal_obligations(uv.def, uv.substs); |
9c376795 FG |
522 | self.out.extend(obligations); |
523 | ||
524 | let predicate = | |
525 | ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct)); | |
526 | let cause = self.cause(traits::WellFormed(None)); | |
527 | self.out.push(traits::Obligation::with_depth( | |
528 | self.tcx(), | |
529 | cause, | |
530 | self.recursion_depth, | |
531 | self.param_env, | |
532 | predicate, | |
533 | )); | |
534 | } | |
f035d41b | 535 | } |
064997fb FG |
536 | ty::ConstKind::Infer(_) => { |
537 | let cause = self.cause(traits::WellFormed(None)); | |
538 | ||
539 | self.out.push(traits::Obligation::with_depth( | |
487cf647 | 540 | self.tcx(), |
064997fb FG |
541 | cause, |
542 | self.recursion_depth, | |
543 | self.param_env, | |
487cf647 | 544 | ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into())), |
064997fb | 545 | )); |
f035d41b | 546 | } |
487cf647 FG |
547 | ty::ConstKind::Expr(_) => { |
548 | // FIXME(generic_const_exprs): this doesnt verify that given `Expr(N + 1)` the | |
549 | // trait bound `typeof(N): Add<typeof(1)>` holds. This is currently unnecessary | |
550 | // as `ConstKind::Expr` is only produced via normalization of `ConstKind::Unevaluated` | |
551 | // which means that the `DefId` would have been typeck'd elsewhere. However in | |
552 | // the future we may allow directly lowering to `ConstKind::Expr` in which case | |
553 | // we would not be proving bounds we should. | |
554 | ||
555 | let predicate = | |
556 | ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct)); | |
557 | let cause = self.cause(traits::WellFormed(None)); | |
558 | self.out.push(traits::Obligation::with_depth( | |
559 | self.tcx(), | |
560 | cause, | |
561 | self.recursion_depth, | |
562 | self.param_env, | |
563 | predicate, | |
564 | )); | |
565 | } | |
566 | ||
f035d41b XL |
567 | ty::ConstKind::Error(_) |
568 | | ty::ConstKind::Param(_) | |
569 | | ty::ConstKind::Bound(..) | |
570 | | ty::ConstKind::Placeholder(..) => { | |
571 | // These variants are trivially WF, so nothing to do here. | |
572 | } | |
573 | ty::ConstKind::Value(..) => { | |
574 | // FIXME: Enforce that values are structurally-matchable. | |
575 | } | |
576 | } | |
577 | continue; | |
578 | } | |
ba9703b0 XL |
579 | }; |
580 | ||
f2b60f7d FG |
581 | debug!("wf bounds for ty={:?} ty.kind={:#?}", ty, ty.kind()); |
582 | ||
1b1a35ee | 583 | match *ty.kind() { |
dfeec247 XL |
584 | ty::Bool |
585 | | ty::Char | |
586 | | ty::Int(..) | |
587 | | ty::Uint(..) | |
588 | | ty::Float(..) | |
f035d41b | 589 | | ty::Error(_) |
dfeec247 XL |
590 | | ty::Str |
591 | | ty::GeneratorWitness(..) | |
9ffffee4 | 592 | | ty::GeneratorWitnessMIR(..) |
dfeec247 XL |
593 | | ty::Never |
594 | | ty::Param(_) | |
595 | | ty::Bound(..) | |
596 | | ty::Placeholder(..) | |
597 | | ty::Foreign(..) => { | |
e9174d1e SL |
598 | // WfScalar, WfParameter, etc |
599 | } | |
600 | ||
f9f354fc XL |
601 | // Can only infer to `ty::Int(_) | ty::Uint(_)`. |
602 | ty::Infer(ty::IntVar(_)) => {} | |
603 | ||
604 | // Can only infer to `ty::Float(_)`. | |
605 | ty::Infer(ty::FloatVar(_)) => {} | |
606 | ||
b7449926 | 607 | ty::Slice(subty) => { |
ea8adc8c XL |
608 | self.require_sized(subty, traits::SliceOrArrayElem); |
609 | } | |
610 | ||
f035d41b | 611 | ty::Array(subty, _) => { |
9e0c209e | 612 | self.require_sized(subty, traits::SliceOrArrayElem); |
f035d41b | 613 | // Note that we handle the len is implicitly checked while walking `arg`. |
a7813a04 XL |
614 | } |
615 | ||
b7449926 | 616 | ty::Tuple(ref tys) => { |
a7813a04 | 617 | if let Some((_last, rest)) = tys.split_last() { |
5e7ed085 FG |
618 | for &elem in rest { |
619 | self.require_sized(elem, traits::TupleElem); | |
e9174d1e | 620 | } |
9cc50fc6 | 621 | } |
e9174d1e SL |
622 | } |
623 | ||
b7449926 | 624 | ty::RawPtr(_) => { |
f035d41b | 625 | // Simple cases that are WF if their type args are WF. |
e9174d1e SL |
626 | } |
627 | ||
9c376795 | 628 | ty::Alias(ty::Projection, data) => { |
f035d41b | 629 | walker.skip_current_subtree(); // Subtree handled by compute_projection. |
e9174d1e SL |
630 | self.compute_projection(data); |
631 | } | |
49aad941 FG |
632 | ty::Alias(ty::Inherent, data) => { |
633 | walker.skip_current_subtree(); // Subtree handled by compute_inherent_projection. | |
634 | self.compute_inherent_projection(data); | |
635 | } | |
e9174d1e | 636 | |
b7449926 | 637 | ty::Adt(def, substs) => { |
e9174d1e | 638 | // WfNominalType |
5e7ed085 | 639 | let obligations = self.nominal_obligations(def.did(), substs); |
e9174d1e SL |
640 | self.out.extend(obligations); |
641 | } | |
642 | ||
0731742a | 643 | ty::FnDef(did, substs) => { |
2b03887a | 644 | let obligations = self.nominal_obligations_without_const(did, substs); |
0731742a XL |
645 | self.out.extend(obligations); |
646 | } | |
647 | ||
b7449926 | 648 | ty::Ref(r, rty, _) => { |
e9174d1e | 649 | // WfReference |
a1dfa0c6 | 650 | if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() { |
e9174d1e | 651 | let cause = self.cause(traits::ReferenceOutlivesReferent(ty)); |
29967ef6 | 652 | self.out.push(traits::Obligation::with_depth( |
487cf647 | 653 | self.tcx(), |
dfeec247 | 654 | cause, |
29967ef6 | 655 | depth, |
dfeec247 | 656 | param_env, |
487cf647 | 657 | ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::TypeOutlives( |
c295e0f8 | 658 | ty::OutlivesPredicate(rty, r), |
487cf647 | 659 | ))), |
dfeec247 | 660 | )); |
e9174d1e SL |
661 | } |
662 | } | |
663 | ||
064997fb | 664 | ty::Generator(did, substs, ..) => { |
ff7c6d11 XL |
665 | // Walk ALL the types in the generator: this will |
666 | // include the upvar types as well as the yield | |
667 | // type. Note that this is mildly distinct from | |
668 | // the closure case, where we have to be careful | |
669 | // about the signature of the closure. We don't | |
670 | // have the problem of implied bounds here since | |
671 | // generators don't take arguments. | |
064997fb FG |
672 | let obligations = self.nominal_obligations(did, substs); |
673 | self.out.extend(obligations); | |
ff7c6d11 XL |
674 | } |
675 | ||
923072b8 | 676 | ty::Closure(did, substs) => { |
ff7c6d11 XL |
677 | // Only check the upvar types for WF, not the rest |
678 | // of the types within. This is needed because we | |
679 | // capture the signature and it may not be WF | |
680 | // without the implied bounds. Consider a closure | |
681 | // like `|x: &'a T|` -- it may be that `T: 'a` is | |
682 | // not known to hold in the creator's context (and | |
683 | // indeed the closure may not be invoked by its | |
684 | // creator, but rather turned to someone who *can* | |
685 | // verify that). | |
686 | // | |
687 | // The special treatment of closures here really | |
688 | // ought not to be necessary either; the problem | |
689 | // is related to #25860 -- there is no way for us | |
690 | // to express a fn type complete with the implied | |
691 | // bounds that it is assuming. I think in reality | |
692 | // the WF rules around fn are a bit messed up, and | |
693 | // that is the rot problem: `fn(&'a T)` should | |
694 | // probably always be WF, because it should be | |
695 | // shorthand for something like `where(T: 'a) { | |
696 | // fn(&'a T) }`, as discussed in #25860. | |
04454e1e FG |
697 | walker.skip_current_subtree(); // subtree handled below |
698 | // FIXME(eddyb) add the type to `walker` instead of recursing. | |
699 | self.compute(substs.as_closure().tupled_upvars_ty().into()); | |
700 | // Note that we cannot skip the generic types | |
701 | // types. Normally, within the fn | |
ff7c6d11 XL |
702 | // body where they are created, the generics will |
703 | // always be WF, and outside of that fn body we | |
704 | // are not directly inspecting closure types | |
705 | // anyway, except via auto trait matching (which | |
706 | // only inspects the upvar types). | |
04454e1e FG |
707 | // But when a closure is part of a type-alias-impl-trait |
708 | // then the function that created the defining site may | |
709 | // have had more bounds available than the type alias | |
710 | // specifies. This may cause us to have a closure in the | |
711 | // hidden type that is not actually well formed and | |
712 | // can cause compiler crashes when the user abuses unsafe | |
713 | // code to procure such a closure. | |
9c376795 | 714 | // See tests/ui/type-alias-impl-trait/wf_check_closures.rs |
923072b8 FG |
715 | let obligations = self.nominal_obligations(did, substs); |
716 | self.out.extend(obligations); | |
e9174d1e SL |
717 | } |
718 | ||
0731742a | 719 | ty::FnPtr(_) => { |
54a0048b | 720 | // let the loop iterate into the argument/return |
9cc50fc6 | 721 | // types appearing in the fn signature |
e9174d1e SL |
722 | } |
723 | ||
9c376795 | 724 | ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { |
064997fb FG |
725 | // All of the requirements on type parameters |
726 | // have already been checked for `impl Trait` in | |
727 | // return position. We do need to check type-alias-impl-trait though. | |
49aad941 | 728 | if self.tcx().is_type_alias_impl_trait(def_id) { |
9c376795 | 729 | let obligations = self.nominal_obligations(def_id, substs); |
8faf50e0 XL |
730 | self.out.extend(obligations); |
731 | } | |
5bcae85e SL |
732 | } |
733 | ||
f2b60f7d | 734 | ty::Dynamic(data, r, _) => { |
e9174d1e SL |
735 | // WfObject |
736 | // | |
737 | // Here, we defer WF checking due to higher-ranked | |
738 | // regions. This is perhaps not ideal. | |
476ff2be | 739 | self.from_object_ty(ty, data, r); |
e9174d1e SL |
740 | |
741 | // FIXME(#27579) RFC also considers adding trait | |
742 | // obligations that don't refer to Self and | |
743 | // checking those | |
744 | ||
f9f354fc | 745 | let defer_to_coercion = self.tcx().features().object_safe_for_dispatch; |
e74abb32 XL |
746 | |
747 | if !defer_to_coercion { | |
064997fb | 748 | let cause = self.cause(traits::WellFormed(None)); |
dfeec247 | 749 | let component_traits = data.auto_traits().chain(data.principal_def_id()); |
f9f354fc | 750 | let tcx = self.tcx(); |
dfeec247 | 751 | self.out.extend(component_traits.map(|did| { |
29967ef6 | 752 | traits::Obligation::with_depth( |
487cf647 | 753 | tcx, |
e74abb32 | 754 | cause.clone(), |
29967ef6 | 755 | depth, |
e74abb32 | 756 | param_env, |
487cf647 | 757 | ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did)), |
dfeec247 XL |
758 | ) |
759 | })); | |
e74abb32 | 760 | } |
e9174d1e SL |
761 | } |
762 | ||
763 | // Inference variables are the complicated case, since we don't | |
764 | // know what type they are. We do two things: | |
765 | // | |
766 | // 1. Check if they have been resolved, and if so proceed with | |
767 | // THAT type. | |
f9f354fc XL |
768 | // 2. If not, we've at least simplified things (e.g., we went |
769 | // from `Vec<$0>: WF` to `$0: WF`), so we can | |
e9174d1e SL |
770 | // register a pending obligation and keep |
771 | // moving. (Goal is that an "inductive hypothesis" | |
772 | // is satisfied to ensure termination.) | |
f9f354fc XL |
773 | // See also the comment on `fn obligations`, describing "livelock" |
774 | // prevention, which happens before this can be reached. | |
b7449926 | 775 | ty::Infer(_) => { |
064997fb FG |
776 | let cause = self.cause(traits::WellFormed(None)); |
777 | self.out.push(traits::Obligation::with_depth( | |
487cf647 | 778 | self.tcx(), |
064997fb FG |
779 | cause, |
780 | self.recursion_depth, | |
781 | param_env, | |
487cf647 | 782 | ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())), |
064997fb | 783 | )); |
e9174d1e SL |
784 | } |
785 | } | |
f2b60f7d FG |
786 | |
787 | debug!(?self.out); | |
e9174d1e | 788 | } |
e9174d1e SL |
789 | } |
790 | ||
064997fb FG |
791 | #[instrument(level = "debug", skip(self))] |
792 | fn nominal_obligations_inner( | |
dfeec247 XL |
793 | &mut self, |
794 | def_id: DefId, | |
795 | substs: SubstsRef<'tcx>, | |
064997fb | 796 | remap_constness: bool, |
dfeec247 | 797 | ) -> Vec<traits::PredicateObligation<'tcx>> { |
49aad941 | 798 | let predicates = self.tcx().predicates_of(def_id); |
1b1a35ee XL |
799 | let mut origins = vec![def_id; predicates.predicates.len()]; |
800 | let mut head = predicates; | |
801 | while let Some(parent) = head.parent { | |
49aad941 | 802 | head = self.tcx().predicates_of(parent); |
1b1a35ee XL |
803 | origins.extend(iter::repeat(parent).take(head.predicates.len())); |
804 | } | |
805 | ||
49aad941 | 806 | let predicates = predicates.instantiate(self.tcx(), substs); |
064997fb | 807 | trace!("{:#?}", predicates); |
1b1a35ee XL |
808 | debug_assert_eq!(predicates.predicates.len(), origins.len()); |
809 | ||
9c376795 | 810 | iter::zip(predicates, origins.into_iter().rev()) |
064997fb | 811 | .map(|((mut pred, span), origin_def_id)| { |
3c0e092e | 812 | let code = if span.is_dummy() { |
f2b60f7d | 813 | traits::ItemObligation(origin_def_id) |
3c0e092e XL |
814 | } else { |
815 | traits::BindingObligation(origin_def_id, span) | |
816 | }; | |
817 | let cause = self.cause(code); | |
064997fb | 818 | if remap_constness { |
49aad941 | 819 | pred = pred.without_const(self.tcx()); |
064997fb | 820 | } |
487cf647 | 821 | traits::Obligation::with_depth( |
49aad941 | 822 | self.tcx(), |
487cf647 FG |
823 | cause, |
824 | self.recursion_depth, | |
825 | self.param_env, | |
826 | pred, | |
827 | ) | |
ba9703b0 | 828 | }) |
dfeec247 XL |
829 | .filter(|pred| !pred.has_escaping_bound_vars()) |
830 | .collect() | |
e9174d1e SL |
831 | } |
832 | ||
064997fb FG |
833 | fn nominal_obligations( |
834 | &mut self, | |
835 | def_id: DefId, | |
836 | substs: SubstsRef<'tcx>, | |
837 | ) -> Vec<traits::PredicateObligation<'tcx>> { | |
838 | self.nominal_obligations_inner(def_id, substs, false) | |
839 | } | |
840 | ||
841 | fn nominal_obligations_without_const( | |
842 | &mut self, | |
843 | def_id: DefId, | |
844 | substs: SubstsRef<'tcx>, | |
845 | ) -> Vec<traits::PredicateObligation<'tcx>> { | |
846 | self.nominal_obligations_inner(def_id, substs, true) | |
847 | } | |
848 | ||
dfeec247 XL |
849 | fn from_object_ty( |
850 | &mut self, | |
851 | ty: Ty<'tcx>, | |
487cf647 | 852 | data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, |
dfeec247 XL |
853 | region: ty::Region<'tcx>, |
854 | ) { | |
e9174d1e SL |
855 | // Imagine a type like this: |
856 | // | |
857 | // trait Foo { } | |
858 | // trait Bar<'c> : 'c { } | |
859 | // | |
860 | // &'b (Foo+'c+Bar<'d>) | |
861 | // ^ | |
862 | // | |
863 | // In this case, the following relationships must hold: | |
864 | // | |
865 | // 'b <= 'c | |
866 | // 'd <= 'c | |
867 | // | |
868 | // The first conditions is due to the normal region pointer | |
869 | // rules, which say that a reference cannot outlive its | |
870 | // referent. | |
871 | // | |
872 | // The final condition may be a bit surprising. In particular, | |
873 | // you may expect that it would have been `'c <= 'd`, since | |
874 | // usually lifetimes of outer things are conservative | |
875 | // approximations for inner things. However, it works somewhat | |
876 | // differently with trait objects: here the idea is that if the | |
877 | // user specifies a region bound (`'c`, in this case) it is the | |
878 | // "master bound" that *implies* that bounds from other traits are | |
879 | // all met. (Remember that *all bounds* in a type like | |
880 | // `Foo+Bar+Zed` must be met, not just one, hence if we write | |
881 | // `Foo<'x>+Bar<'y>`, we know that the type outlives *both* 'x and | |
882 | // 'y.) | |
883 | // | |
884 | // Note: in fact we only permit builtin traits, not `Bar<'d>`, I | |
885 | // am looking forward to the future here. | |
532ac7d7 | 886 | if !data.has_escaping_bound_vars() && !region.has_escaping_bound_vars() { |
49aad941 | 887 | let implicit_bounds = object_region_bounds(self.tcx(), data); |
e9174d1e | 888 | |
476ff2be | 889 | let explicit_bound = region; |
e9174d1e | 890 | |
0bf4aa26 | 891 | self.out.reserve(implicit_bounds.len()); |
e9174d1e | 892 | for implicit_bound in implicit_bounds { |
c30ab7b3 | 893 | let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound)); |
dfeec247 XL |
894 | let outlives = |
895 | ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound)); | |
29967ef6 | 896 | self.out.push(traits::Obligation::with_depth( |
49aad941 | 897 | self.tcx(), |
dfeec247 | 898 | cause, |
29967ef6 | 899 | self.recursion_depth, |
dfeec247 | 900 | self.param_env, |
487cf647 | 901 | outlives, |
dfeec247 | 902 | )); |
e9174d1e SL |
903 | } |
904 | } | |
905 | } | |
906 | } | |
907 | ||
9fa01778 | 908 | /// Given an object type like `SomeTrait + Send`, computes the lifetime |
e9174d1e SL |
909 | /// bounds that must hold on the elided self type. These are derived |
910 | /// from the declarations of `SomeTrait`, `Send`, and friends -- if | |
911 | /// they declare `trait SomeTrait : 'static`, for example, then | |
912 | /// `'static` would appear in the list. The hard work is done by | |
dfeec247 | 913 | /// `infer::required_region_bounds`, see that for more information. |
dc9dc135 XL |
914 | pub fn object_region_bounds<'tcx>( |
915 | tcx: TyCtxt<'tcx>, | |
487cf647 | 916 | existential_predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, |
dc9dc135 | 917 | ) -> Vec<ty::Region<'tcx>> { |
e9174d1e SL |
918 | // Since we don't actually *know* the self type for an object, |
919 | // this "open(err)" serves as a kind of dummy standin -- basically | |
0bf4aa26 | 920 | // a placeholder type. |
9ffffee4 | 921 | let open_ty = tcx.mk_fresh_ty(0); |
e9174d1e | 922 | |
ba9703b0 | 923 | let predicates = existential_predicates.iter().filter_map(|predicate| { |
f035d41b | 924 | if let ty::ExistentialPredicate::Projection(_) = predicate.skip_binder() { |
ba9703b0 XL |
925 | None |
926 | } else { | |
927 | Some(predicate.with_self_ty(tcx, open_ty)) | |
60c5eb7d | 928 | } |
ba9703b0 | 929 | }); |
60c5eb7d | 930 | |
ba9703b0 | 931 | required_region_bounds(tcx, open_ty, predicates) |
60c5eb7d | 932 | } |
064997fb FG |
933 | |
934 | /// Given a set of predicates that apply to an object type, returns | |
935 | /// the region bounds that the (erased) `Self` type must | |
936 | /// outlive. Precisely *because* the `Self` type is erased, the | |
937 | /// parameter `erased_self_ty` must be supplied to indicate what type | |
938 | /// has been used to represent `Self` in the predicates | |
939 | /// themselves. This should really be a unique type; `FreshTy(0)` is a | |
940 | /// popular choice. | |
941 | /// | |
942 | /// N.B., in some cases, particularly around higher-ranked bounds, | |
943 | /// this function returns a kind of conservative approximation. | |
944 | /// That is, all regions returned by this function are definitely | |
945 | /// required, but there may be other region bounds that are not | |
946 | /// returned, as well as requirements like `for<'a> T: 'a`. | |
947 | /// | |
948 | /// Requires that trait definitions have been processed so that we can | |
949 | /// elaborate predicates and walk supertraits. | |
f2b60f7d | 950 | #[instrument(skip(tcx, predicates), level = "debug", ret)] |
064997fb FG |
951 | pub(crate) fn required_region_bounds<'tcx>( |
952 | tcx: TyCtxt<'tcx>, | |
953 | erased_self_ty: Ty<'tcx>, | |
954 | predicates: impl Iterator<Item = ty::Predicate<'tcx>>, | |
955 | ) -> Vec<ty::Region<'tcx>> { | |
956 | assert!(!erased_self_ty.has_escaping_bound_vars()); | |
957 | ||
353b0b11 FG |
958 | traits::elaborate(tcx, predicates) |
959 | .filter_map(|pred| { | |
960 | debug!(?pred); | |
961 | match pred.kind().skip_binder() { | |
487cf647 FG |
962 | ty::PredicateKind::Clause(ty::Clause::Projection(..)) |
963 | | ty::PredicateKind::Clause(ty::Clause::Trait(..)) | |
9ffffee4 | 964 | | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) |
064997fb FG |
965 | | ty::PredicateKind::Subtype(..) |
966 | | ty::PredicateKind::Coerce(..) | |
967 | | ty::PredicateKind::WellFormed(..) | |
968 | | ty::PredicateKind::ObjectSafe(..) | |
969 | | ty::PredicateKind::ClosureKind(..) | |
487cf647 | 970 | | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) |
064997fb FG |
971 | | ty::PredicateKind::ConstEvaluatable(..) |
972 | | ty::PredicateKind::ConstEquate(..) | |
487cf647 | 973 | | ty::PredicateKind::Ambiguous |
353b0b11 | 974 | | ty::PredicateKind::AliasRelate(..) |
064997fb | 975 | | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, |
487cf647 FG |
976 | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate( |
977 | ref t, | |
978 | ref r, | |
979 | ))) => { | |
064997fb FG |
980 | // Search for a bound of the form `erased_self_ty |
981 | // : 'a`, but be wary of something like `for<'a> | |
982 | // erased_self_ty : 'a` (we interpret a | |
983 | // higher-ranked bound like that as 'static, | |
984 | // though at present the code in `fulfill.rs` | |
985 | // considers such bounds to be unsatisfiable, so | |
986 | // it's kind of a moot point since you could never | |
987 | // construct such an object, but this seems | |
988 | // correct even if that code changes). | |
989 | if t == &erased_self_ty && !r.has_escaping_bound_vars() { | |
990 | Some(*r) | |
991 | } else { | |
992 | None | |
993 | } | |
994 | } | |
995 | } | |
996 | }) | |
997 | .collect() | |
998 | } |