wf.rs 26.3 KB
Newer Older
M
Mark Mansi 已提交
1
use crate::infer::InferCtxt;
C
Camille GILLOT 已提交
2
use crate::opaque_types::required_region_bounds;
3
use crate::traits;
4 5
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
6
use rustc_hir::lang_items;
7
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
M
Mazdak Farrokhzad 已提交
8
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
9
use rustc_span::Span;
10
use std::rc::Rc;
11 12 13 14 15 16 17

/// Returns the set of obligations needed to make `ty` well-formed.
/// If `ty` contains unresolved inference variables, this may include
/// further WF obligations. However, if `ty` IS an unresolved
/// inference variable, returns `None`, because we are not able to
/// make any progress at all. This is to prevent "livelock" where we
/// say "$0 is WF if $0 is WF".
18 19 20 21 22 23 24
pub fn obligations<'a, 'tcx>(
    infcx: &InferCtxt<'a, 'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    body_id: hir::HirId,
    ty: Ty<'tcx>,
    span: Span,
) -> Option<Vec<traits::PredicateObligation<'tcx>>> {
M
Mark Rousskov 已提交
25
    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
26 27
    if wf.compute(ty) {
        debug!("wf::obligations({:?}, body_id={:?}) = {:?}", ty, body_id, wf.out);
28

29 30 31 32 33 34 35 36 37 38 39 40
        let result = wf.normalize();
        debug!("wf::obligations({:?}, body_id={:?}) ~~> {:?}", ty, body_id, result);
        Some(result)
    } else {
        None // no progress made, return None
    }
}

/// Returns the obligations that make this trait reference
/// well-formed.  For example, if there is a trait `Set` defined like
/// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF
/// if `Bar: Eq`.
41 42 43 44 45 46
pub fn trait_obligations<'a, 'tcx>(
    infcx: &InferCtxt<'a, 'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    body_id: hir::HirId,
    trait_ref: &ty::TraitRef<'tcx>,
    span: Span,
C
Camille GILLOT 已提交
47
    item: Option<&'tcx hir::Item<'tcx>>,
48
) -> Vec<traits::PredicateObligation<'tcx>> {
49
    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item };
50
    wf.compute_trait_ref(trait_ref, Elaborate::All);
51 52 53
    wf.normalize()
}

54 55 56 57 58 59 60
pub fn predicate_obligations<'a, 'tcx>(
    infcx: &InferCtxt<'a, 'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    body_id: hir::HirId,
    predicate: &ty::Predicate<'tcx>,
    span: Span,
) -> Vec<traits::PredicateObligation<'tcx>> {
61
    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
62 63 64

    // (*) ok to skip binders, because wf code is prepared for it
    match *predicate {
65
        ty::Predicate::Trait(ref t, _) => {
66
            wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*)
67
        }
M
Mark Rousskov 已提交
68
        ty::Predicate::RegionOutlives(..) => {}
69 70 71 72 73 74 75 76 77 78 79
        ty::Predicate::TypeOutlives(ref t) => {
            wf.compute(t.skip_binder().0);
        }
        ty::Predicate::Projection(ref t) => {
            let t = t.skip_binder(); // (*)
            wf.compute_projection(t.projection_ty);
            wf.compute(t.ty);
        }
        ty::Predicate::WellFormed(t) => {
            wf.compute(t);
        }
M
Mark Rousskov 已提交
80 81
        ty::Predicate::ObjectSafe(_) => {}
        ty::Predicate::ClosureKind(..) => {}
N
Niko Matsakis 已提交
82 83 84 85
        ty::Predicate::Subtype(ref data) => {
            wf.compute(data.skip_binder().a); // (*)
            wf.compute(data.skip_binder().b); // (*)
        }
86 87 88 89 90 91 92 93
        ty::Predicate::ConstEvaluatable(def_id, substs) => {
            let obligations = wf.nominal_obligations(def_id, substs);
            wf.out.extend(obligations);

            for ty in substs.types() {
                wf.compute(ty);
            }
        }
94 95 96 97 98
    }

    wf.normalize()
}

99
struct WfPredicates<'a, 'tcx> {
100
    infcx: &'a InferCtxt<'a, 'tcx>,
N
Niko Matsakis 已提交
101
    param_env: ty::ParamEnv<'tcx>,
L
ljedrz 已提交
102
    body_id: hir::HirId,
103 104
    span: Span,
    out: Vec<traits::PredicateObligation<'tcx>>,
C
Camille GILLOT 已提交
105
    item: Option<&'tcx hir::Item<'tcx>>,
106 107
}

N
Niko Matsakis 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
/// Controls whether we "elaborate" supertraits and so forth on the WF
/// predicates. This is a kind of hack to address #43784. The
/// underlying problem in that issue was a trait structure like:
///
/// ```
/// trait Foo: Copy { }
/// trait Bar: Foo { }
/// impl<T: Bar> Foo for T { }
/// impl<T> Bar for T { }
/// ```
///
/// Here, in the `Foo` impl, we will check that `T: Copy` holds -- but
/// we decide that this is true because `T: Bar` is in the
/// where-clauses (and we can elaborate that to include `T:
/// Copy`). This wouldn't be a problem, except that when we check the
/// `Bar` impl, we decide that `T: Foo` must hold because of the `Foo`
/// impl. And so nowhere did we check that `T: Copy` holds!
///
/// To resolve this, we elaborate the WF requirements that must be
/// proven when checking impls. This means that (e.g.) the `impl Bar
/// for T` will be forced to prove not only that `T: Foo` but also `T:
/// Copy` (which it won't be able to do, because there is no `Copy`
/// impl for `T`).
131 132 133 134 135 136
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
enum Elaborate {
    All,
    None,
}

137 138 139 140 141 142
fn extend_cause_with_original_assoc_item_obligation<'tcx>(
    tcx: TyCtxt<'tcx>,
    trait_ref: &ty::TraitRef<'tcx>,
    item: Option<&hir::Item<'tcx>>,
    cause: &mut traits::ObligationCause<'tcx>,
    pred: &ty::Predicate<'_>,
E
Esteban Küber 已提交
143
    mut trait_assoc_items: impl Iterator<Item = &'tcx ty::AssocItem>,
144
) {
145 146 147 148 149 150 151
    debug!(
        "extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}",
        trait_ref, item, cause, pred
    );
    let items = match item {
        Some(hir::Item { kind: hir::ItemKind::Impl { items, .. }, .. }) => items,
        _ => return,
152
    };
153 154 155 156 157
    let fix_span =
        |impl_item_ref: &hir::ImplItemRef<'_>| match tcx.hir().impl_item(impl_item_ref.id).kind {
            hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::TyAlias(ty) => ty.span,
            _ => impl_item_ref.span,
        };
158 159 160 161
    match pred {
        ty::Predicate::Projection(proj) => {
            // The obligation comes not from the current `impl` nor the `trait` being
            // implemented, but rather from a "second order" obligation, like in
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
            // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs`.
            let trait_assoc_item = tcx.associated_item(proj.projection_def_id());
            if let Some(impl_item_span) =
                items.iter().find(|item| item.ident == trait_assoc_item.ident).map(fix_span)
            {
                cause.span = impl_item_span;
            } else {
                let kind = &proj.ty().skip_binder().kind;
                if let ty::Projection(projection_ty) = kind {
                    // This happens when an associated type has a projection coming from another
                    // associated type. See `traits-assoc-type-in-supertrait-bad.rs`.
                    let trait_assoc_item = tcx.associated_item(projection_ty.item_def_id);
                    if let Some(impl_item_span) =
                        items.iter().find(|item| item.ident == trait_assoc_item.ident).map(fix_span)
                    {
                        cause.span = impl_item_span;
                    }
179 180 181
                }
            }
        }
182 183 184 185 186 187
        ty::Predicate::Trait(pred, _) => {
            // An associated item obligation born out of the `trait` failed to be met. An example
            // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
            debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
            if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) =
                &pred.skip_binder().self_ty().kind
188
            {
189
                if let Some(impl_item_span) = trait_assoc_items
190 191
                    .find(|i| i.def_id == *item_def_id)
                    .and_then(|trait_assoc_item| {
192
                        items.iter().find(|i| i.ident == trait_assoc_item.ident).map(fix_span)
193 194
                    })
                {
195
                    cause.span = impl_item_span;
196 197 198 199 200 201 202
                }
            }
        }
        _ => {}
    }
}

203
impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
204
    fn cause(&mut self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> {
205
        traits::ObligationCause::new(self.span, self.body_id, code)
206 207 208 209 210
    }

    fn normalize(&mut self) -> Vec<traits::PredicateObligation<'tcx>> {
        let cause = self.cause(traits::MiscObligation);
        let infcx = &mut self.infcx;
N
Niko Matsakis 已提交
211
        let param_env = self.param_env;
212 213 214
        let mut obligations = Vec::with_capacity(self.out.len());
        for pred in &self.out {
            assert!(!pred.has_escaping_bound_vars());
215 216 217 218 219
            let mut selcx = traits::SelectionContext::new(infcx);
            let i = obligations.len();
            let value =
                traits::normalize_to(&mut selcx, param_env, cause.clone(), pred, &mut obligations);
            obligations.insert(i, value);
220
        }
221
        obligations
222 223
    }

224
    /// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
225
    fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) {
226
        let tcx = self.infcx.tcx;
227 228
        let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs);

229
        debug!("compute_trait_ref obligations {:?}", obligations);
230
        let cause = self.cause(traits::MiscObligation);
N
Niko Matsakis 已提交
231
        let param_env = self.param_env;
232

233
        let item = self.item;
234

E
Esteban Küber 已提交
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
        let extend = |obligation: traits::PredicateObligation<'tcx>| {
            let mut cause = cause.clone();
            if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() {
                let derived_cause = traits::DerivedObligationCause {
                    parent_trait_ref,
                    parent_code: Rc::new(obligation.cause.code.clone()),
                };
                cause.code = traits::ObligationCauseCode::DerivedObligation(derived_cause);
            }
            extend_cause_with_original_assoc_item_obligation(
                tcx,
                trait_ref,
                item,
                &mut cause,
                &obligation.predicate,
                tcx.associated_items(trait_ref.def_id).in_definition_order(),
            );
            traits::Obligation::new(cause, param_env, obligation.predicate)
        };

255
        if let Elaborate::All = elaborate {
E
Esteban Küber 已提交
256 257
            let implied_obligations = traits::util::elaborate_obligations(tcx, obligations);
            let implied_obligations = implied_obligations.map(extend);
258
            self.out.extend(implied_obligations);
E
Esteban Küber 已提交
259 260
        } else {
            self.out.extend(obligations);
261
        }
262

M
Mark Rousskov 已提交
263 264 265
        self.out.extend(trait_ref.substs.types().filter(|ty| !ty.has_escaping_bound_vars()).map(
            |ty| traits::Obligation::new(cause.clone(), param_env, ty::Predicate::WellFormed(ty)),
        ));
266 267 268 269 270 271
    }

    /// Pushes the obligations required for `trait_ref::Item` to be WF
    /// into `self.out`.
    fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
        // A projection is well-formed if (a) the trait ref itself is
G
Georg Brandl 已提交
272
        // WF and (b) the trait-ref holds.  (It may also be
273
        // normalizable and be WF that way.)
274
        let trait_ref = data.trait_ref(self.infcx.tcx);
275
        self.compute_trait_ref(&trait_ref, Elaborate::None);
276

277
        if !data.has_escaping_bound_vars() {
278
            let predicate = trait_ref.without_const().to_predicate();
279
            let cause = self.cause(traits::ProjectionWf(data));
N
Niko Matsakis 已提交
280
            self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
281 282 283
        }
    }

284
    /// Pushes the obligations required for an array length to be WF
285
    /// into `self.out`.
O
Oliver Scherer 已提交
286
    fn compute_array_len(&mut self, constant: ty::Const<'tcx>) {
287 288 289
        if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.val {
            assert!(promoted.is_none());

290 291 292 293 294
            let obligations = self.nominal_obligations(def_id, substs);
            self.out.extend(obligations);

            let predicate = ty::Predicate::ConstEvaluatable(def_id, substs);
            let cause = self.cause(traits::MiscObligation);
M
Mark Rousskov 已提交
295
            self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
296 297
        }
    }
298

299
    fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
300
        if !subty.has_escaping_bound_vars() {
301
            let cause = self.cause(cause);
302
            let trait_ref = ty::TraitRef {
303
                def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
304 305
                substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
            };
306 307 308 309 310
            self.out.push(traits::Obligation::new(
                cause,
                self.param_env,
                trait_ref.without_const().to_predicate(),
            ));
311 312 313
        }
    }

A
Alexander Regueiro 已提交
314
    /// Pushes new obligations into `out`. Returns `true` if it was able
315 316 317 318
    /// to generate all the predicates needed to validate that `ty0`
    /// is WF. Returns false if `ty0` is an unresolved type variable,
    /// in which case we are not able to simplify at all.
    fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
319
        let mut walker = ty0.walk();
N
Niko Matsakis 已提交
320
        let param_env = self.param_env;
321 322 323 324 325 326 327 328 329 330 331 332 333
        while let Some(arg) = walker.next() {
            let ty = match arg.unpack() {
                GenericArgKind::Type(ty) => ty,

                // No WF constraints for lifetimes being present, any outlives
                // obligations are handled by the parent (e.g. `ty::Ref`).
                GenericArgKind::Lifetime(_) => continue,

                // FIXME(eddyb) this is wrong and needs to be replaced
                // (see https://github.com/rust-lang/rust/pull/70107).
                GenericArgKind::Const(_) => continue,
            };

V
varkor 已提交
334
            match ty.kind {
M
Mark Rousskov 已提交
335 336 337 338 339 340 341 342 343 344 345 346 347
                ty::Bool
                | ty::Char
                | ty::Int(..)
                | ty::Uint(..)
                | ty::Float(..)
                | ty::Error
                | ty::Str
                | ty::GeneratorWitness(..)
                | ty::Never
                | ty::Param(_)
                | ty::Bound(..)
                | ty::Placeholder(..)
                | ty::Foreign(..) => {
348 349 350
                    // WfScalar, WfParameter, etc
                }

V
varkor 已提交
351
                ty::Slice(subty) => {
352 353 354
                    self.require_sized(subty, traits::SliceOrArrayElem);
                }

V
varkor 已提交
355
                ty::Array(subty, len) => {
356
                    self.require_sized(subty, traits::SliceOrArrayElem);
357
                    // FIXME(eddyb) handle `GenericArgKind::Const` above instead.
358
                    self.compute_array_len(*len);
359 360
                }

V
varkor 已提交
361
                ty::Tuple(ref tys) => {
362 363
                    if let Some((_last, rest)) = tys.split_last() {
                        for elem in rest {
V
varkor 已提交
364
                            self.require_sized(elem.expect_ty(), traits::TupleElem);
365
                        }
366
                    }
367 368
                }

V
varkor 已提交
369
                ty::RawPtr(_) => {
370 371 372
                    // simple cases that are WF if their type args are WF
                }

V
varkor 已提交
373
                ty::Projection(data) => {
374
                    walker.skip_current_subtree(); // subtree handled by compute_projection
375 376 377
                    self.compute_projection(data);
                }

378 379
                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),

V
varkor 已提交
380
                ty::Adt(def, substs) => {
381 382 383 384 385
                    // WfNominalType
                    let obligations = self.nominal_obligations(def.did, substs);
                    self.out.extend(obligations);
                }

386 387 388 389 390
                ty::FnDef(did, substs) => {
                    let obligations = self.nominal_obligations(did, substs);
                    self.out.extend(obligations);
                }

V
varkor 已提交
391
                ty::Ref(r, rty, _) => {
392
                    // WfReference
393
                    if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
394
                        let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
M
Mark Rousskov 已提交
395 396 397 398 399 400 401
                        self.out.push(traits::Obligation::new(
                            cause,
                            param_env,
                            ty::Predicate::TypeOutlives(ty::Binder::dummy(ty::OutlivesPredicate(
                                rty, r,
                            ))),
                        ));
402 403 404
                    }
                }

V
varkor 已提交
405
                ty::Generator(..) => {
N
Niko Matsakis 已提交
406 407 408 409 410 411 412
                    // Walk ALL the types in the generator: this will
                    // include the upvar types as well as the yield
                    // type. Note that this is mildly distinct from
                    // the closure case, where we have to be careful
                    // about the signature of the closure. We don't
                    // have the problem of implied bounds here since
                    // generators don't take arguments.
413 414
                }

415
                ty::Closure(_, substs) => {
N
Niko Matsakis 已提交
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
                    // Only check the upvar types for WF, not the rest
                    // of the types within. This is needed because we
                    // capture the signature and it may not be WF
                    // without the implied bounds. Consider a closure
                    // like `|x: &'a T|` -- it may be that `T: 'a` is
                    // not known to hold in the creator's context (and
                    // indeed the closure may not be invoked by its
                    // creator, but rather turned to someone who *can*
                    // verify that).
                    //
                    // The special treatment of closures here really
                    // ought not to be necessary either; the problem
                    // is related to #25860 -- there is no way for us
                    // to express a fn type complete with the implied
                    // bounds that it is assuming. I think in reality
                    // the WF rules around fn are a bit messed up, and
                    // that is the rot problem: `fn(&'a T)` should
                    // probably always be WF, because it should be
                    // shorthand for something like `where(T: 'a) {
                    // fn(&'a T) }`, as discussed in #25860.
436 437 438 439 440 441 442 443 444
                    //
                    // Note that we are also skipping the generic
                    // types. This is consistent with the `outlives`
                    // code, but anyway doesn't matter: within the fn
                    // body where they are created, the generics will
                    // always be WF, and outside of that fn body we
                    // are not directly inspecting closure types
                    // anyway, except via auto trait matching (which
                    // only inspects the upvar types).
445
                    walker.skip_current_subtree(); // subtree handled by compute_projection
446
                    for upvar_ty in substs.as_closure().upvar_tys() {
447 448 449 450
                        self.compute(upvar_ty);
                    }
                }

451
                ty::FnPtr(_) => {
452
                    // let the loop iterate into the argument/return
453
                    // types appearing in the fn signature
454 455
                }

456
                ty::Opaque(did, substs) => {
457 458 459
                    // all of the requirements on type parameters
                    // should've been checked by the instantiation
                    // of whatever returned this exact `impl Trait`.
460

V
varkor 已提交
461
                    // for named opaque `impl Trait` types we still need to check them
C
Camille GILLOT 已提交
462
                    if ty::is_impl_trait_defn(self.infcx.tcx, did).is_none() {
463 464 465
                        let obligations = self.nominal_obligations(did, substs);
                        self.out.extend(obligations);
                    }
466 467
                }

V
varkor 已提交
468
                ty::Dynamic(data, r) => {
469 470 471 472
                    // WfObject
                    //
                    // Here, we defer WF checking due to higher-ranked
                    // regions. This is perhaps not ideal.
473
                    self.from_object_ty(ty, data, r);
474 475 476 477 478

                    // FIXME(#27579) RFC also considers adding trait
                    // obligations that don't refer to Self and
                    // checking those

M
Mark Rousskov 已提交
479
                    let defer_to_coercion = self.infcx.tcx.features().object_safe_for_dispatch;
480 481 482

                    if !defer_to_coercion {
                        let cause = self.cause(traits::MiscObligation);
M
Mark Rousskov 已提交
483 484 485
                        let component_traits = data.auto_traits().chain(data.principal_def_id());
                        self.out.extend(component_traits.map(|did| {
                            traits::Obligation::new(
486 487
                                cause.clone(),
                                param_env,
M
Mark Rousskov 已提交
488 489 490
                                ty::Predicate::ObjectSafe(did),
                            )
                        }));
491
                    }
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
                }

                // Inference variables are the complicated case, since we don't
                // know what type they are. We do two things:
                //
                // 1. Check if they have been resolved, and if so proceed with
                //    THAT type.
                // 2. If not, check whether this is the type that we
                //    started with (ty0). In that case, we've made no
                //    progress at all, so return false. Otherwise,
                //    we've at least simplified things (i.e., we went
                //    from `Vec<$0>: WF` to `$0: WF`, so we can
                //    register a pending obligation and keep
                //    moving. (Goal is that an "inductive hypothesis"
                //    is satisfied to ensure termination.)
V
varkor 已提交
507
                ty::Infer(_) => {
V
varkor 已提交
508
                    let ty = self.infcx.shallow_resolve(ty);
M
Mark Rousskov 已提交
509 510 511 512
                    if let ty::Infer(_) = ty.kind {
                        // not yet resolved...
                        if ty == ty0 {
                            // ...this is the type we started from! no progress.
513 514 515 516
                            return false;
                        }

                        let cause = self.cause(traits::MiscObligation);
M
Mark Rousskov 已提交
517 518 519 520 521 522 523 524
                        self.out.push(
                            // ...not the type we started from, so we made progress.
                            traits::Obligation::new(
                                cause,
                                self.param_env,
                                ty::Predicate::WellFormed(ty),
                            ),
                        );
525 526 527
                    } else {
                        // Yes, resolved, proceed with the
                        // result. Should never return false because
V
varkor 已提交
528
                        // `ty` is not a Infer.
529 530 531 532 533 534 535
                        assert!(self.compute(ty));
                    }
                }
            }
        }

        // if we made it through that loop above, we made progress!
536
        true
537 538
    }

M
Mark Rousskov 已提交
539 540 541 542 543 544 545 546 547
    fn nominal_obligations(
        &mut self,
        def_id: DefId,
        substs: SubstsRef<'tcx>,
    ) -> Vec<traits::PredicateObligation<'tcx>> {
        let predicates = self.infcx.tcx.predicates_of(def_id).instantiate(self.infcx.tcx, substs);
        predicates
            .predicates
            .into_iter()
548 549 550 551 552
            .zip(predicates.spans.into_iter())
            .map(|(pred, span)| {
                let cause = self.cause(traits::BindingObligation(def_id, span));
                traits::Obligation::new(cause, self.param_env, pred)
            })
M
Mark Rousskov 已提交
553 554
            .filter(|pred| !pred.has_escaping_bound_vars())
            .collect()
555 556
    }

M
Mark Rousskov 已提交
557 558 559 560 561 562
    fn from_object_ty(
        &mut self,
        ty: Ty<'tcx>,
        data: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
        region: ty::Region<'tcx>,
    ) {
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
        // Imagine a type like this:
        //
        //     trait Foo { }
        //     trait Bar<'c> : 'c { }
        //
        //     &'b (Foo+'c+Bar<'d>)
        //         ^
        //
        // In this case, the following relationships must hold:
        //
        //     'b <= 'c
        //     'd <= 'c
        //
        // The first conditions is due to the normal region pointer
        // rules, which say that a reference cannot outlive its
        // referent.
        //
        // The final condition may be a bit surprising. In particular,
        // you may expect that it would have been `'c <= 'd`, since
        // usually lifetimes of outer things are conservative
        // approximations for inner things. However, it works somewhat
        // differently with trait objects: here the idea is that if the
        // user specifies a region bound (`'c`, in this case) it is the
        // "master bound" that *implies* that bounds from other traits are
        // all met. (Remember that *all bounds* in a type like
        // `Foo+Bar+Zed` must be met, not just one, hence if we write
        // `Foo<'x>+Bar<'y>`, we know that the type outlives *both* 'x and
        // 'y.)
        //
        // Note: in fact we only permit builtin traits, not `Bar<'d>`, I
        // am looking forward to the future here.
594
        if !data.has_escaping_bound_vars() && !region.has_escaping_bound_vars() {
M
Mark Rousskov 已提交
595
            let implicit_bounds = object_region_bounds(self.infcx.tcx, data);
596

597
            let explicit_bound = region;
598

L
ljedrz 已提交
599
            self.out.reserve(implicit_bounds.len());
600
            for implicit_bound in implicit_bounds {
601
                let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound));
M
Mark Rousskov 已提交
602 603 604 605 606 607 608
                let outlives =
                    ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound));
                self.out.push(traits::Obligation::new(
                    cause,
                    self.param_env,
                    outlives.to_predicate(),
                ));
609 610 611 612 613
            }
        }
    }
}

A
Alexander Regueiro 已提交
614
/// Given an object type like `SomeTrait + Send`, computes the lifetime
615 616 617 618
/// bounds that must hold on the elided self type. These are derived
/// from the declarations of `SomeTrait`, `Send`, and friends -- if
/// they declare `trait SomeTrait : 'static`, for example, then
/// `'static` would appear in the list. The hard work is done by
619
/// `infer::required_region_bounds`, see that for more information.
620 621
pub fn object_region_bounds<'tcx>(
    tcx: TyCtxt<'tcx>,
622 623
    existential_predicates: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
) -> Vec<ty::Region<'tcx>> {
624 625
    // Since we don't actually *know* the self type for an object,
    // this "open(err)" serves as a kind of dummy standin -- basically
N
Niko Matsakis 已提交
626
    // a placeholder type.
G
Gabriel Smith 已提交
627
    let open_ty = tcx.mk_ty_infer(ty::FreshTy(0));
628

629 630 631 632 633 634 635
    let predicates = existential_predicates.iter().filter_map(|predicate| {
        if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() {
            None
        } else {
            Some(predicate.with_self_ty(tcx, open_ty))
        }
    });
636

637
    required_region_bounds(tcx, open_ty, predicates)
638
}