1 use crate::infer
::InferCtxt
;
2 use crate::opaque_types
::required_region_bounds
;
5 use rustc_hir
::def_id
::DefId
;
6 use rustc_hir
::lang_items
::LangItem
;
7 use rustc_middle
::ty
::subst
::{GenericArg, GenericArgKind, SubstsRef}
;
8 use rustc_middle
::ty
::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}
;
13 /// Returns the set of obligations needed to make `arg` well-formed.
14 /// If `arg` contains unresolved inference variables, this may include
15 /// further WF obligations. However, if `arg` IS an unresolved
16 /// inference variable, returns `None`, because we are not able to
17 /// make any progress at all. This is to prevent "livelock" where we
18 /// say "$0 is WF if $0 is WF".
19 pub fn obligations
<'a
, 'tcx
>(
20 infcx
: &InferCtxt
<'a
, 'tcx
>,
21 param_env
: ty
::ParamEnv
<'tcx
>,
23 arg
: GenericArg
<'tcx
>,
25 ) -> Option
<Vec
<traits
::PredicateObligation
<'tcx
>>> {
26 // Handle the "livelock" case (see comment above) by bailing out if necessary.
27 let arg
= match arg
.unpack() {
28 GenericArgKind
::Type(ty
) => {
30 ty
::Infer(ty
::TyVar(_
)) => {
31 let resolved_ty
= infcx
.shallow_resolve(ty
);
32 if resolved_ty
== ty
{
33 // No progress, bail out to prevent "livelock".
43 GenericArgKind
::Const(ct
) => {
45 ty
::ConstKind
::Infer(infer
) => {
46 let resolved
= infcx
.shallow_resolve(infer
);
47 if resolved
== infer
{
52 infcx
.tcx
.mk_const(ty
::Const { val: ty::ConstKind::Infer(resolved), ty: ct.ty }
)
58 // There is nothing we have to do for lifetimes.
59 GenericArgKind
::Lifetime(..) => return Some(Vec
::new()),
62 let mut wf
= WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None }
;
64 debug
!("wf::obligations({:?}, body_id={:?}) = {:?}", arg
, body_id
, wf
.out
);
66 let result
= wf
.normalize();
67 debug
!("wf::obligations({:?}, body_id={:?}) ~~> {:?}", arg
, body_id
, result
);
71 /// Returns the obligations that make this trait reference
72 /// well-formed. For example, if there is a trait `Set` defined like
73 /// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF
75 pub fn trait_obligations
<'a
, 'tcx
>(
76 infcx
: &InferCtxt
<'a
, 'tcx
>,
77 param_env
: ty
::ParamEnv
<'tcx
>,
79 trait_ref
: &ty
::TraitRef
<'tcx
>,
81 item
: Option
<&'tcx hir
::Item
<'tcx
>>,
82 ) -> Vec
<traits
::PredicateObligation
<'tcx
>> {
83 let mut wf
= WfPredicates { infcx, param_env, body_id, span, out: vec![], item }
;
84 wf
.compute_trait_ref(trait_ref
, Elaborate
::All
);
88 pub fn predicate_obligations
<'a
, 'tcx
>(
89 infcx
: &InferCtxt
<'a
, 'tcx
>,
90 param_env
: ty
::ParamEnv
<'tcx
>,
92 predicate
: ty
::Predicate
<'tcx
>,
94 ) -> Vec
<traits
::PredicateObligation
<'tcx
>> {
95 let mut wf
= WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None }
;
97 // It's ok to skip the binder here because wf code is prepared for it
98 match predicate
.skip_binders() {
99 ty
::PredicateAtom
::Trait(t
, _
) => {
100 wf
.compute_trait_ref(&t
.trait_ref
, Elaborate
::None
);
102 ty
::PredicateAtom
::RegionOutlives(..) => {}
103 ty
::PredicateAtom
::TypeOutlives(ty
::OutlivesPredicate(ty
, _reg
)) => {
104 wf
.compute(ty
.into());
106 ty
::PredicateAtom
::Projection(t
) => {
107 wf
.compute_projection(t
.projection_ty
);
108 wf
.compute(t
.ty
.into());
110 ty
::PredicateAtom
::WellFormed(arg
) => {
113 ty
::PredicateAtom
::ObjectSafe(_
) => {}
114 ty
::PredicateAtom
::ClosureKind(..) => {}
115 ty
::PredicateAtom
::Subtype(ty
::SubtypePredicate { a, b, a_is_expected: _ }
) => {
116 wf
.compute(a
.into());
117 wf
.compute(b
.into());
119 ty
::PredicateAtom
::ConstEvaluatable(def
, substs
) => {
120 let obligations
= wf
.nominal_obligations(def
.did
, substs
);
121 wf
.out
.extend(obligations
);
123 for arg
in substs
.iter() {
127 ty
::PredicateAtom
::ConstEquate(c1
, c2
) => {
128 wf
.compute(c1
.into());
129 wf
.compute(c2
.into());
131 ty
::PredicateAtom
::TypeWellFormedFromEnv(..) => {
132 bug
!("TypeWellFormedFromEnv is only used for Chalk")
139 struct WfPredicates
<'a
, 'tcx
> {
140 infcx
: &'a InferCtxt
<'a
, 'tcx
>,
141 param_env
: ty
::ParamEnv
<'tcx
>,
144 out
: Vec
<traits
::PredicateObligation
<'tcx
>>,
145 item
: Option
<&'tcx hir
::Item
<'tcx
>>,
148 /// Controls whether we "elaborate" supertraits and so forth on the WF
149 /// predicates. This is a kind of hack to address #43784. The
150 /// underlying problem in that issue was a trait structure like:
153 /// trait Foo: Copy { }
154 /// trait Bar: Foo { }
155 /// impl<T: Bar> Foo for T { }
156 /// impl<T> Bar for T { }
159 /// Here, in the `Foo` impl, we will check that `T: Copy` holds -- but
160 /// we decide that this is true because `T: Bar` is in the
161 /// where-clauses (and we can elaborate that to include `T:
162 /// Copy`). This wouldn't be a problem, except that when we check the
163 /// `Bar` impl, we decide that `T: Foo` must hold because of the `Foo`
164 /// impl. And so nowhere did we check that `T: Copy` holds!
166 /// To resolve this, we elaborate the WF requirements that must be
167 /// proven when checking impls. This means that (e.g.) the `impl Bar
168 /// for T` will be forced to prove not only that `T: Foo` but also `T:
169 /// Copy` (which it won't be able to do, because there is no `Copy`
171 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
177 fn extend_cause_with_original_assoc_item_obligation
<'tcx
>(
179 trait_ref
: &ty
::TraitRef
<'tcx
>,
180 item
: Option
<&hir
::Item
<'tcx
>>,
181 cause
: &mut traits
::ObligationCause
<'tcx
>,
182 pred
: &ty
::Predicate
<'tcx
>,
183 mut trait_assoc_items
: impl Iterator
<Item
= &'tcx ty
::AssocItem
>,
186 "extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}",
187 trait_ref
, item
, cause
, pred
189 let items
= match item
{
190 Some(hir
::Item { kind: hir::ItemKind::Impl { items, .. }
, .. }) => items
,
194 |impl_item_ref
: &hir
::ImplItemRef
<'_
>| match tcx
.hir().impl_item(impl_item_ref
.id
).kind
{
195 hir
::ImplItemKind
::Const(ty
, _
) | hir
::ImplItemKind
::TyAlias(ty
) => ty
.span
,
196 _
=> impl_item_ref
.span
,
199 // It is fine to skip the binder as we don't care about regions here.
200 match pred
.skip_binders() {
201 ty
::PredicateAtom
::Projection(proj
) => {
202 // The obligation comes not from the current `impl` nor the `trait` being implemented,
203 // but rather from a "second order" obligation, where an associated type has a
204 // projection coming from another associated type. See
205 // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and
206 // `traits-assoc-type-in-supertrait-bad.rs`.
207 if let ty
::Projection(projection_ty
) = proj
.ty
.kind() {
208 let trait_assoc_item
= tcx
.associated_item(projection_ty
.item_def_id
);
209 if let Some(impl_item_span
) =
210 items
.iter().find(|item
| item
.ident
== trait_assoc_item
.ident
).map(fix_span
)
212 cause
.make_mut().span
= impl_item_span
;
216 ty
::PredicateAtom
::Trait(pred
, _
) => {
217 // An associated item obligation born out of the `trait` failed to be met. An example
218 // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
219 debug
!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred
);
220 if let ty
::Projection(ty
::ProjectionTy { item_def_id, .. }
) = *pred
.self_ty().kind() {
221 if let Some(impl_item_span
) = trait_assoc_items
222 .find(|i
| i
.def_id
== item_def_id
)
223 .and_then(|trait_assoc_item
| {
224 items
.iter().find(|i
| i
.ident
== trait_assoc_item
.ident
).map(fix_span
)
227 cause
.make_mut().span
= impl_item_span
;
235 impl<'a
, 'tcx
> WfPredicates
<'a
, 'tcx
> {
236 fn tcx(&self) -> TyCtxt
<'tcx
> {
240 fn cause(&self, code
: traits
::ObligationCauseCode
<'tcx
>) -> traits
::ObligationCause
<'tcx
> {
241 traits
::ObligationCause
::new(self.span
, self.body_id
, code
)
244 fn normalize(&mut self) -> Vec
<traits
::PredicateObligation
<'tcx
>> {
245 let cause
= self.cause(traits
::MiscObligation
);
246 let infcx
= &mut self.infcx
;
247 let param_env
= self.param_env
;
248 let mut obligations
= Vec
::with_capacity(self.out
.len());
249 for pred
in &self.out
{
250 assert
!(!pred
.has_escaping_bound_vars());
251 let mut selcx
= traits
::SelectionContext
::new(infcx
);
252 let i
= obligations
.len();
254 traits
::normalize_to(&mut selcx
, param_env
, cause
.clone(), pred
, &mut obligations
);
255 obligations
.insert(i
, value
);
260 /// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
261 fn compute_trait_ref(&mut self, trait_ref
: &ty
::TraitRef
<'tcx
>, elaborate
: Elaborate
) {
262 let tcx
= self.infcx
.tcx
;
263 let obligations
= self.nominal_obligations(trait_ref
.def_id
, trait_ref
.substs
);
265 debug
!("compute_trait_ref obligations {:?}", obligations
);
266 let cause
= self.cause(traits
::MiscObligation
);
267 let param_env
= self.param_env
;
269 let item
= self.item
;
271 let extend
= |obligation
: traits
::PredicateObligation
<'tcx
>| {
272 let mut cause
= cause
.clone();
273 if let Some(parent_trait_ref
) = obligation
.predicate
.to_opt_poly_trait_ref() {
274 let derived_cause
= traits
::DerivedObligationCause
{
276 parent_code
: Rc
::new(obligation
.cause
.code
.clone()),
278 cause
.make_mut().code
=
279 traits
::ObligationCauseCode
::DerivedObligation(derived_cause
);
281 extend_cause_with_original_assoc_item_obligation(
286 &obligation
.predicate
,
287 tcx
.associated_items(trait_ref
.def_id
).in_definition_order(),
289 traits
::Obligation
::new(cause
, param_env
, obligation
.predicate
)
292 if let Elaborate
::All
= elaborate
{
293 let implied_obligations
= traits
::util
::elaborate_obligations(tcx
, obligations
);
294 let implied_obligations
= implied_obligations
.map(extend
);
295 self.out
.extend(implied_obligations
);
297 self.out
.extend(obligations
);
300 let tcx
= self.tcx();
307 matches
!(arg
.unpack(), GenericArgKind
::Type(..) | GenericArgKind
::Const(..))
309 .filter(|(_
, arg
)| !arg
.has_escaping_bound_vars())
311 let mut new_cause
= cause
.clone();
312 // The first subst is the self ty - use the correct span for it.
314 if let Some(hir
::ItemKind
::Impl { self_ty, .. }
) = item
.map(|i
| &i
.kind
) {
315 new_cause
.make_mut().span
= self_ty
.span
;
318 traits
::Obligation
::new(
321 ty
::PredicateAtom
::WellFormed(arg
).to_predicate(tcx
),
327 /// Pushes the obligations required for `trait_ref::Item` to be WF
329 fn compute_projection(&mut self, data
: ty
::ProjectionTy
<'tcx
>) {
330 // A projection is well-formed if (a) the trait ref itself is
331 // WF and (b) the trait-ref holds. (It may also be
332 // normalizable and be WF that way.)
333 let trait_ref
= data
.trait_ref(self.infcx
.tcx
);
334 self.compute_trait_ref(&trait_ref
, Elaborate
::None
);
336 if !data
.has_escaping_bound_vars() {
337 let predicate
= trait_ref
.without_const().to_predicate(self.infcx
.tcx
);
338 let cause
= self.cause(traits
::ProjectionWf(data
));
339 self.out
.push(traits
::Obligation
::new(cause
, self.param_env
, predicate
));
343 fn require_sized(&mut self, subty
: Ty
<'tcx
>, cause
: traits
::ObligationCauseCode
<'tcx
>) {
344 if !subty
.has_escaping_bound_vars() {
345 let cause
= self.cause(cause
);
346 let trait_ref
= ty
::TraitRef
{
347 def_id
: self.infcx
.tcx
.require_lang_item(LangItem
::Sized
, None
),
348 substs
: self.infcx
.tcx
.mk_substs_trait(subty
, &[]),
350 self.out
.push(traits
::Obligation
::new(
353 trait_ref
.without_const().to_predicate(self.infcx
.tcx
),
358 /// Pushes all the predicates needed to validate that `ty` is WF into `out`.
359 fn compute(&mut self, arg
: GenericArg
<'tcx
>) {
360 let mut walker
= arg
.walk();
361 let param_env
= self.param_env
;
362 while let Some(arg
) = walker
.next() {
363 let ty
= match arg
.unpack() {
364 GenericArgKind
::Type(ty
) => ty
,
366 // No WF constraints for lifetimes being present, any outlives
367 // obligations are handled by the parent (e.g. `ty::Ref`).
368 GenericArgKind
::Lifetime(_
) => continue,
370 GenericArgKind
::Const(constant
) => {
372 ty
::ConstKind
::Unevaluated(def
, substs
, promoted
) => {
373 assert
!(promoted
.is_none());
375 let obligations
= self.nominal_obligations(def
.did
, substs
);
376 self.out
.extend(obligations
);
378 let predicate
= ty
::PredicateAtom
::ConstEvaluatable(def
, substs
)
379 .to_predicate(self.tcx());
380 let cause
= self.cause(traits
::MiscObligation
);
381 self.out
.push(traits
::Obligation
::new(
387 ty
::ConstKind
::Infer(infer
) => {
388 let resolved
= self.infcx
.shallow_resolve(infer
);
389 // the `InferConst` changed, meaning that we made progress.
390 if resolved
!= infer
{
391 let cause
= self.cause(traits
::MiscObligation
);
393 let resolved_constant
= self.infcx
.tcx
.mk_const(ty
::Const
{
394 val
: ty
::ConstKind
::Infer(resolved
),
397 self.out
.push(traits
::Obligation
::new(
400 ty
::PredicateAtom
::WellFormed(resolved_constant
.into())
401 .to_predicate(self.tcx()),
405 ty
::ConstKind
::Error(_
)
406 | ty
::ConstKind
::Param(_
)
407 | ty
::ConstKind
::Bound(..)
408 | ty
::ConstKind
::Placeholder(..) => {
409 // These variants are trivially WF, so nothing to do here.
411 ty
::ConstKind
::Value(..) => {
412 // FIXME: Enforce that values are structurally-matchable.
427 | ty
::GeneratorWitness(..)
431 | ty
::Placeholder(..)
432 | ty
::Foreign(..) => {
433 // WfScalar, WfParameter, etc
436 // Can only infer to `ty::Int(_) | ty::Uint(_)`.
437 ty
::Infer(ty
::IntVar(_
)) => {}
439 // Can only infer to `ty::Float(_)`.
440 ty
::Infer(ty
::FloatVar(_
)) => {}
442 ty
::Slice(subty
) => {
443 self.require_sized(subty
, traits
::SliceOrArrayElem
);
446 ty
::Array(subty
, _
) => {
447 self.require_sized(subty
, traits
::SliceOrArrayElem
);
448 // Note that we handle the len is implicitly checked while walking `arg`.
451 ty
::Tuple(ref tys
) => {
452 if let Some((_last
, rest
)) = tys
.split_last() {
454 self.require_sized(elem
.expect_ty(), traits
::TupleElem
);
460 // Simple cases that are WF if their type args are WF.
463 ty
::Projection(data
) => {
464 walker
.skip_current_subtree(); // Subtree handled by compute_projection.
465 self.compute_projection(data
);
468 ty
::Adt(def
, substs
) => {
470 let obligations
= self.nominal_obligations(def
.did
, substs
);
471 self.out
.extend(obligations
);
474 ty
::FnDef(did
, substs
) => {
475 let obligations
= self.nominal_obligations(did
, substs
);
476 self.out
.extend(obligations
);
479 ty
::Ref(r
, rty
, _
) => {
481 if !r
.has_escaping_bound_vars() && !rty
.has_escaping_bound_vars() {
482 let cause
= self.cause(traits
::ReferenceOutlivesReferent(ty
));
483 self.out
.push(traits
::Obligation
::new(
486 ty
::PredicateAtom
::TypeOutlives(ty
::OutlivesPredicate(rty
, r
))
487 .to_predicate(self.tcx()),
492 ty
::Generator(..) => {
493 // Walk ALL the types in the generator: this will
494 // include the upvar types as well as the yield
495 // type. Note that this is mildly distinct from
496 // the closure case, where we have to be careful
497 // about the signature of the closure. We don't
498 // have the problem of implied bounds here since
499 // generators don't take arguments.
502 ty
::Closure(_
, substs
) => {
503 // Only check the upvar types for WF, not the rest
504 // of the types within. This is needed because we
505 // capture the signature and it may not be WF
506 // without the implied bounds. Consider a closure
507 // like `|x: &'a T|` -- it may be that `T: 'a` is
508 // not known to hold in the creator's context (and
509 // indeed the closure may not be invoked by its
510 // creator, but rather turned to someone who *can*
513 // The special treatment of closures here really
514 // ought not to be necessary either; the problem
515 // is related to #25860 -- there is no way for us
516 // to express a fn type complete with the implied
517 // bounds that it is assuming. I think in reality
518 // the WF rules around fn are a bit messed up, and
519 // that is the rot problem: `fn(&'a T)` should
520 // probably always be WF, because it should be
521 // shorthand for something like `where(T: 'a) {
522 // fn(&'a T) }`, as discussed in #25860.
524 // Note that we are also skipping the generic
525 // types. This is consistent with the `outlives`
526 // code, but anyway doesn't matter: within the fn
527 // body where they are created, the generics will
528 // always be WF, and outside of that fn body we
529 // are not directly inspecting closure types
530 // anyway, except via auto trait matching (which
531 // only inspects the upvar types).
532 walker
.skip_current_subtree(); // subtree handled below
533 for upvar_ty
in substs
.as_closure().upvar_tys() {
534 // FIXME(eddyb) add the type to `walker` instead of recursing.
535 self.compute(upvar_ty
.into());
540 // let the loop iterate into the argument/return
541 // types appearing in the fn signature
544 ty
::Opaque(did
, substs
) => {
545 // all of the requirements on type parameters
546 // should've been checked by the instantiation
547 // of whatever returned this exact `impl Trait`.
549 // for named opaque `impl Trait` types we still need to check them
550 if ty
::is_impl_trait_defn(self.infcx
.tcx
, did
).is_none() {
551 let obligations
= self.nominal_obligations(did
, substs
);
552 self.out
.extend(obligations
);
556 ty
::Dynamic(data
, r
) => {
559 // Here, we defer WF checking due to higher-ranked
560 // regions. This is perhaps not ideal.
561 self.from_object_ty(ty
, data
, r
);
563 // FIXME(#27579) RFC also considers adding trait
564 // obligations that don't refer to Self and
567 let defer_to_coercion
= self.tcx().features().object_safe_for_dispatch
;
569 if !defer_to_coercion
{
570 let cause
= self.cause(traits
::MiscObligation
);
571 let component_traits
= data
.auto_traits().chain(data
.principal_def_id());
572 let tcx
= self.tcx();
573 self.out
.extend(component_traits
.map(|did
| {
574 traits
::Obligation
::new(
577 ty
::PredicateAtom
::ObjectSafe(did
).to_predicate(tcx
),
583 // Inference variables are the complicated case, since we don't
584 // know what type they are. We do two things:
586 // 1. Check if they have been resolved, and if so proceed with
588 // 2. If not, we've at least simplified things (e.g., we went
589 // from `Vec<$0>: WF` to `$0: WF`), so we can
590 // register a pending obligation and keep
591 // moving. (Goal is that an "inductive hypothesis"
592 // is satisfied to ensure termination.)
593 // See also the comment on `fn obligations`, describing "livelock"
594 // prevention, which happens before this can be reached.
596 let ty
= self.infcx
.shallow_resolve(ty
);
597 if let ty
::Infer(ty
::TyVar(_
)) = ty
.kind() {
598 // Not yet resolved, but we've made progress.
599 let cause
= self.cause(traits
::MiscObligation
);
600 self.out
.push(traits
::Obligation
::new(
603 ty
::PredicateAtom
::WellFormed(ty
.into()).to_predicate(self.tcx()),
606 // Yes, resolved, proceed with the result.
607 // FIXME(eddyb) add the type to `walker` instead of recursing.
608 self.compute(ty
.into());
615 fn nominal_obligations(
618 substs
: SubstsRef
<'tcx
>,
619 ) -> Vec
<traits
::PredicateObligation
<'tcx
>> {
620 let predicates
= self.infcx
.tcx
.predicates_of(def_id
);
621 let mut origins
= vec
![def_id
; predicates
.predicates
.len()];
622 let mut head
= predicates
;
623 while let Some(parent
) = head
.parent
{
624 head
= self.infcx
.tcx
.predicates_of(parent
);
625 origins
.extend(iter
::repeat(parent
).take(head
.predicates
.len()));
628 let predicates
= predicates
.instantiate(self.infcx
.tcx
, substs
);
629 debug_assert_eq
!(predicates
.predicates
.len(), origins
.len());
634 .zip(predicates
.spans
.into_iter())
635 .zip(origins
.into_iter().rev())
636 .map(|((pred
, span
), origin_def_id
)| {
637 let cause
= self.cause(traits
::BindingObligation(origin_def_id
, span
));
638 traits
::Obligation
::new(cause
, self.param_env
, pred
)
640 .filter(|pred
| !pred
.has_escaping_bound_vars())
647 data
: ty
::Binder
<&'tcx ty
::List
<ty
::ExistentialPredicate
<'tcx
>>>,
648 region
: ty
::Region
<'tcx
>,
650 // Imagine a type like this:
653 // trait Bar<'c> : 'c { }
655 // &'b (Foo+'c+Bar<'d>)
658 // In this case, the following relationships must hold:
663 // The first conditions is due to the normal region pointer
664 // rules, which say that a reference cannot outlive its
667 // The final condition may be a bit surprising. In particular,
668 // you may expect that it would have been `'c <= 'd`, since
669 // usually lifetimes of outer things are conservative
670 // approximations for inner things. However, it works somewhat
671 // differently with trait objects: here the idea is that if the
672 // user specifies a region bound (`'c`, in this case) it is the
673 // "master bound" that *implies* that bounds from other traits are
674 // all met. (Remember that *all bounds* in a type like
675 // `Foo+Bar+Zed` must be met, not just one, hence if we write
676 // `Foo<'x>+Bar<'y>`, we know that the type outlives *both* 'x and
679 // Note: in fact we only permit builtin traits, not `Bar<'d>`, I
680 // am looking forward to the future here.
681 if !data
.has_escaping_bound_vars() && !region
.has_escaping_bound_vars() {
682 let implicit_bounds
= object_region_bounds(self.infcx
.tcx
, data
);
684 let explicit_bound
= region
;
686 self.out
.reserve(implicit_bounds
.len());
687 for implicit_bound
in implicit_bounds
{
688 let cause
= self.cause(traits
::ObjectTypeBound(ty
, explicit_bound
));
690 ty
::Binder
::dummy(ty
::OutlivesPredicate(explicit_bound
, implicit_bound
));
691 self.out
.push(traits
::Obligation
::new(
694 outlives
.to_predicate(self.infcx
.tcx
),
701 /// Given an object type like `SomeTrait + Send`, computes the lifetime
702 /// bounds that must hold on the elided self type. These are derived
703 /// from the declarations of `SomeTrait`, `Send`, and friends -- if
704 /// they declare `trait SomeTrait : 'static`, for example, then
705 /// `'static` would appear in the list. The hard work is done by
706 /// `infer::required_region_bounds`, see that for more information.
707 pub fn object_region_bounds
<'tcx
>(
709 existential_predicates
: ty
::Binder
<&'tcx ty
::List
<ty
::ExistentialPredicate
<'tcx
>>>,
710 ) -> Vec
<ty
::Region
<'tcx
>> {
711 // Since we don't actually *know* the self type for an object,
712 // this "open(err)" serves as a kind of dummy standin -- basically
713 // a placeholder type.
714 let open_ty
= tcx
.mk_ty_infer(ty
::FreshTy(0));
716 let predicates
= existential_predicates
.iter().filter_map(|predicate
| {
717 if let ty
::ExistentialPredicate
::Projection(_
) = predicate
.skip_binder() {
720 Some(predicate
.with_self_ty(tcx
, open_ty
))
724 required_region_bounds(tcx
, open_ty
, predicates
)