2012-12-03 18:48:01 -06:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2014-04-14 10:30:31 -05:00
|
|
|
// #![warn(deprecated_mode)]
|
2012-08-08 14:58:22 -05:00
|
|
|
|
2015-02-13 18:52:55 -06:00
|
|
|
use middle::infer::{InferCtxt, GenericKind};
|
2015-03-28 04:23:20 -05:00
|
|
|
use middle::subst::Substs;
|
2015-02-13 18:52:55 -06:00
|
|
|
use middle::traits;
|
2015-06-23 13:50:50 -05:00
|
|
|
use middle::ty::{self, RegionEscape, ToPolyTraitRef, ToPredicate, Ty};
|
2015-02-13 18:52:55 -06:00
|
|
|
use middle::ty_fold::{TypeFoldable, TypeFolder};
|
2014-03-08 14:36:22 -06:00
|
|
|
|
2014-08-27 20:46:52 -05:00
|
|
|
use syntax::ast;
|
2015-02-13 18:52:55 -06:00
|
|
|
use syntax::codemap::Span;
|
2014-08-27 20:46:52 -05:00
|
|
|
|
2015-02-13 18:52:55 -06:00
|
|
|
use util::common::ErrorReported;
|
2015-03-03 18:27:50 -06:00
|
|
|
use util::nodemap::FnvHashSet;
|
2012-12-13 15:05:22 -06:00
|
|
|
|
2012-05-16 10:51:16 -05:00
|
|
|
// Helper functions related to manipulating region types.
|
|
|
|
|
2015-06-18 00:51:23 -05:00
|
|
|
#[derive(Debug)]
|
2015-02-04 09:48:29 -06:00
|
|
|
pub enum Implication<'tcx> {
|
|
|
|
RegionSubRegion(Option<Ty<'tcx>>, ty::Region, ty::Region),
|
|
|
|
RegionSubGeneric(Option<Ty<'tcx>>, ty::Region, GenericKind<'tcx>),
|
2015-02-28 18:34:16 -06:00
|
|
|
RegionSubClosure(Option<Ty<'tcx>>, ty::Region, ast::DefId, &'tcx Substs<'tcx>),
|
2015-02-13 18:52:55 -06:00
|
|
|
Predicate(ast::DefId, ty::Predicate<'tcx>),
|
2014-08-27 20:46:52 -05:00
|
|
|
}
|
|
|
|
|
2015-02-04 09:48:29 -06:00
|
|
|
struct Implicator<'a, 'tcx: 'a> {
|
2015-02-13 18:52:55 -06:00
|
|
|
infcx: &'a InferCtxt<'a,'tcx>,
|
|
|
|
body_id: ast::NodeId,
|
2014-09-29 14:11:30 -05:00
|
|
|
stack: Vec<(ty::Region, Option<Ty<'tcx>>)>,
|
2015-02-13 18:52:55 -06:00
|
|
|
span: Span,
|
2015-02-04 09:48:29 -06:00
|
|
|
out: Vec<Implication<'tcx>>,
|
2015-03-03 18:27:50 -06:00
|
|
|
visited: FnvHashSet<Ty<'tcx>>,
|
2014-08-27 20:46:52 -05:00
|
|
|
}
|
|
|
|
|
2014-11-25 20:17:11 -06:00
|
|
|
/// This routine computes the well-formedness constraints that must hold for the type `ty` to
|
|
|
|
/// appear in a context with lifetime `outer_region`
|
2015-02-13 18:52:55 -06:00
|
|
|
pub fn implications<'a,'tcx>(
|
|
|
|
infcx: &'a InferCtxt<'a,'tcx>,
|
|
|
|
body_id: ast::NodeId,
|
2014-09-29 14:11:30 -05:00
|
|
|
ty: Ty<'tcx>,
|
2015-02-13 18:52:55 -06:00
|
|
|
outer_region: ty::Region,
|
|
|
|
span: Span)
|
2015-02-04 09:48:29 -06:00
|
|
|
-> Vec<Implication<'tcx>>
|
2014-08-27 20:46:52 -05:00
|
|
|
{
|
2015-06-18 12:25:05 -05:00
|
|
|
debug!("implications(body_id={}, ty={:?}, outer_region={:?})",
|
2015-02-13 18:52:55 -06:00
|
|
|
body_id,
|
2015-06-18 12:25:05 -05:00
|
|
|
ty,
|
|
|
|
outer_region);
|
2015-02-13 18:52:55 -06:00
|
|
|
|
2014-08-27 20:46:52 -05:00
|
|
|
let mut stack = Vec::new();
|
|
|
|
stack.push((outer_region, None));
|
2015-06-30 04:18:03 -05:00
|
|
|
let mut wf = Implicator { infcx: infcx,
|
2015-02-13 18:52:55 -06:00
|
|
|
body_id: body_id,
|
|
|
|
span: span,
|
|
|
|
stack: stack,
|
2015-03-03 18:27:50 -06:00
|
|
|
out: Vec::new(),
|
|
|
|
visited: FnvHashSet() };
|
2014-08-27 20:46:52 -05:00
|
|
|
wf.accumulate_from_ty(ty);
|
2015-06-18 12:25:05 -05:00
|
|
|
debug!("implications: out={:?}", wf.out);
|
2014-08-27 20:46:52 -05:00
|
|
|
wf.out
|
|
|
|
}
|
2013-10-29 05:03:32 -05:00
|
|
|
|
2015-02-04 09:48:29 -06:00
|
|
|
impl<'a, 'tcx> Implicator<'a, 'tcx> {
|
2015-02-13 18:52:55 -06:00
|
|
|
fn tcx(&self) -> &'a ty::ctxt<'tcx> {
|
|
|
|
self.infcx.tcx
|
|
|
|
}
|
|
|
|
|
2014-09-29 14:11:30 -05:00
|
|
|
fn accumulate_from_ty(&mut self, ty: Ty<'tcx>) {
|
2015-06-18 12:25:05 -05:00
|
|
|
debug!("accumulate_from_ty(ty={:?})",
|
|
|
|
ty);
|
2013-10-29 05:03:32 -05:00
|
|
|
|
2015-03-03 18:27:50 -06:00
|
|
|
// When expanding out associated types, we can visit a cyclic
|
|
|
|
// set of types. Issue #23003.
|
|
|
|
if !self.visited.insert(ty) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-31 03:51:16 -05:00
|
|
|
match ty.sty {
|
2015-06-11 18:21:46 -05:00
|
|
|
ty::TyBool |
|
|
|
|
ty::TyChar |
|
|
|
|
ty::TyInt(..) |
|
|
|
|
ty::TyUint(..) |
|
|
|
|
ty::TyFloat(..) |
|
|
|
|
ty::TyBareFn(..) |
|
|
|
|
ty::TyError |
|
|
|
|
ty::TyStr => {
|
2014-08-27 20:46:52 -05:00
|
|
|
// No borrowed content reachable here.
|
|
|
|
}
|
2013-10-29 05:03:32 -05:00
|
|
|
|
2015-06-11 18:21:46 -05:00
|
|
|
ty::TyClosure(def_id, substs) => {
|
2015-02-28 18:34:16 -06:00
|
|
|
let &(r_a, opt_ty) = self.stack.last().unwrap();
|
|
|
|
self.out.push(Implication::RegionSubClosure(opt_ty, r_a, def_id, substs));
|
2014-08-27 20:46:52 -05:00
|
|
|
}
|
2013-10-29 05:03:32 -05:00
|
|
|
|
2015-06-11 18:21:46 -05:00
|
|
|
ty::TyTrait(ref t) => {
|
2014-12-07 10:10:48 -06:00
|
|
|
let required_region_bounds =
|
2015-02-13 18:52:55 -06:00
|
|
|
object_region_bounds(self.tcx(), &t.principal, t.bounds.builtin_bounds);
|
2014-12-07 10:10:48 -06:00
|
|
|
self.accumulate_from_object_ty(ty, t.bounds.region_bound, required_region_bounds)
|
2013-04-02 00:32:37 -05:00
|
|
|
}
|
2013-10-29 05:03:32 -05:00
|
|
|
|
2015-06-11 18:21:46 -05:00
|
|
|
ty::TyEnum(def_id, substs) |
|
|
|
|
ty::TyStruct(def_id, substs) => {
|
2015-06-25 15:42:17 -05:00
|
|
|
let item_scheme = self.tcx().lookup_item_type(def_id);
|
2014-12-28 09:07:21 -06:00
|
|
|
self.accumulate_from_adt(ty, def_id, &item_scheme.generics, substs)
|
2014-08-27 20:46:52 -05:00
|
|
|
}
|
2013-10-29 05:03:32 -05:00
|
|
|
|
2015-06-11 18:21:46 -05:00
|
|
|
ty::TyArray(t, _) |
|
2015-06-12 18:50:13 -05:00
|
|
|
ty::TySlice(t) |
|
2015-07-08 14:27:32 -05:00
|
|
|
ty::TyRawPtr(ty::TypeWithMutability { ty: t, .. }) |
|
2015-06-11 18:21:46 -05:00
|
|
|
ty::TyBox(t) => {
|
2014-08-27 20:46:52 -05:00
|
|
|
self.accumulate_from_ty(t)
|
|
|
|
}
|
|
|
|
|
2015-06-11 18:21:46 -05:00
|
|
|
ty::TyRef(r_b, mt) => {
|
2014-12-04 18:52:57 -06:00
|
|
|
self.accumulate_from_rptr(ty, *r_b, mt.ty);
|
2014-08-27 20:46:52 -05:00
|
|
|
}
|
|
|
|
|
2015-06-11 18:21:46 -05:00
|
|
|
ty::TyParam(p) => {
|
2014-08-27 20:46:52 -05:00
|
|
|
self.push_param_constraint_from_top(p);
|
|
|
|
}
|
2013-04-02 00:32:37 -05:00
|
|
|
|
2015-06-11 18:21:46 -05:00
|
|
|
ty::TyProjection(ref data) => {
|
2014-12-17 13:16:28 -06:00
|
|
|
// `<T as TraitRef<..>>::Name`
|
|
|
|
|
2015-01-03 03:40:33 -06:00
|
|
|
self.push_projection_constraint_from_top(data);
|
2014-12-17 13:16:28 -06:00
|
|
|
}
|
|
|
|
|
2015-06-11 18:21:46 -05:00
|
|
|
ty::TyTuple(ref tuptys) => {
|
2015-01-31 11:20:46 -06:00
|
|
|
for &tupty in tuptys {
|
2014-08-27 20:46:52 -05:00
|
|
|
self.accumulate_from_ty(tupty);
|
2013-10-29 05:03:32 -05:00
|
|
|
}
|
2013-04-02 00:32:37 -05:00
|
|
|
}
|
2014-08-27 20:46:52 -05:00
|
|
|
|
2015-06-11 18:21:46 -05:00
|
|
|
ty::TyInfer(_) => {
|
2014-08-27 20:46:52 -05:00
|
|
|
// This should not happen, BUT:
|
|
|
|
//
|
|
|
|
// Currently we uncover region relationships on
|
|
|
|
// entering the fn check. We should do this after
|
|
|
|
// the fn check, then we can call this case a bug().
|
|
|
|
}
|
2013-04-02 00:32:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-27 20:46:52 -05:00
|
|
|
fn accumulate_from_rptr(&mut self,
|
2014-09-29 14:11:30 -05:00
|
|
|
ty: Ty<'tcx>,
|
2014-08-27 20:46:52 -05:00
|
|
|
r_b: ty::Region,
|
2014-09-29 14:11:30 -05:00
|
|
|
ty_b: Ty<'tcx>) {
|
2014-08-27 20:46:52 -05:00
|
|
|
// We are walking down a type like this, and current
|
|
|
|
// position is indicated by caret:
|
|
|
|
//
|
|
|
|
// &'a &'b ty_b
|
|
|
|
// ^
|
|
|
|
//
|
|
|
|
// At this point, top of stack will be `'a`. We must
|
|
|
|
// require that `'a <= 'b`.
|
|
|
|
|
|
|
|
self.push_region_constraint_from_top(r_b);
|
|
|
|
|
|
|
|
// Now we push `'b` onto the stack, because it must
|
|
|
|
// constrain any borrowed content we find within `T`.
|
2013-04-02 00:32:37 -05:00
|
|
|
|
2014-08-27 20:46:52 -05:00
|
|
|
self.stack.push((r_b, Some(ty)));
|
|
|
|
self.accumulate_from_ty(ty_b);
|
|
|
|
self.stack.pop().unwrap();
|
|
|
|
}
|
|
|
|
|
2014-11-25 20:17:11 -06:00
|
|
|
/// Pushes a constraint that `r_b` must outlive the top region on the stack.
|
2014-08-27 20:46:52 -05:00
|
|
|
fn push_region_constraint_from_top(&mut self,
|
|
|
|
r_b: ty::Region) {
|
|
|
|
|
|
|
|
// Indicates that we have found borrowed content with a lifetime
|
|
|
|
// of at least `r_b`. This adds a constraint that `r_b` must
|
|
|
|
// outlive the region `r_a` on top of the stack.
|
|
|
|
//
|
|
|
|
// As an example, imagine walking a type like:
|
|
|
|
//
|
|
|
|
// &'a &'b T
|
|
|
|
// ^
|
|
|
|
//
|
|
|
|
// when we hit the inner pointer (indicated by caret), `'a` will
|
|
|
|
// be on top of stack and `'b` will be the lifetime of the content
|
|
|
|
// we just found. So we add constraint that `'a <= 'b`.
|
|
|
|
|
|
|
|
let &(r_a, opt_ty) = self.stack.last().unwrap();
|
|
|
|
self.push_sub_region_constraint(opt_ty, r_a, r_b);
|
|
|
|
}
|
2013-04-02 00:32:37 -05:00
|
|
|
|
2014-11-25 20:17:11 -06:00
|
|
|
/// Pushes a constraint that `r_a <= r_b`, due to `opt_ty`
|
2014-08-27 20:46:52 -05:00
|
|
|
fn push_sub_region_constraint(&mut self,
|
2014-09-29 14:11:30 -05:00
|
|
|
opt_ty: Option<Ty<'tcx>>,
|
2014-08-27 20:46:52 -05:00
|
|
|
r_a: ty::Region,
|
|
|
|
r_b: ty::Region) {
|
2015-02-04 09:48:29 -06:00
|
|
|
self.out.push(Implication::RegionSubRegion(opt_ty, r_a, r_b));
|
2013-04-02 00:32:37 -05:00
|
|
|
}
|
|
|
|
|
2014-11-25 20:17:11 -06:00
|
|
|
/// Pushes a constraint that `param_ty` must outlive the top region on the stack.
|
2014-08-27 20:46:52 -05:00
|
|
|
fn push_param_constraint_from_top(&mut self,
|
|
|
|
param_ty: ty::ParamTy) {
|
|
|
|
let &(region, opt_ty) = self.stack.last().unwrap();
|
|
|
|
self.push_param_constraint(region, opt_ty, param_ty);
|
|
|
|
}
|
|
|
|
|
2015-01-03 03:40:33 -06:00
|
|
|
/// Pushes a constraint that `projection_ty` must outlive the top region on the stack.
|
|
|
|
fn push_projection_constraint_from_top(&mut self,
|
|
|
|
projection_ty: &ty::ProjectionTy<'tcx>) {
|
|
|
|
let &(region, opt_ty) = self.stack.last().unwrap();
|
2015-02-04 09:48:29 -06:00
|
|
|
self.out.push(Implication::RegionSubGeneric(
|
2015-01-03 03:40:33 -06:00
|
|
|
opt_ty, region, GenericKind::Projection(projection_ty.clone())));
|
|
|
|
}
|
|
|
|
|
2014-11-25 20:17:11 -06:00
|
|
|
/// Pushes a constraint that `region <= param_ty`, due to `opt_ty`
|
2014-08-27 20:46:52 -05:00
|
|
|
fn push_param_constraint(&mut self,
|
|
|
|
region: ty::Region,
|
2014-09-29 14:11:30 -05:00
|
|
|
opt_ty: Option<Ty<'tcx>>,
|
2014-08-27 20:46:52 -05:00
|
|
|
param_ty: ty::ParamTy) {
|
2015-02-04 09:48:29 -06:00
|
|
|
self.out.push(Implication::RegionSubGeneric(
|
2015-01-03 03:40:33 -06:00
|
|
|
opt_ty, region, GenericKind::Param(param_ty)));
|
2014-08-27 20:46:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn accumulate_from_adt(&mut self,
|
2014-09-29 14:11:30 -05:00
|
|
|
ty: Ty<'tcx>,
|
2014-08-27 20:46:52 -05:00
|
|
|
def_id: ast::DefId,
|
2015-02-13 18:52:55 -06:00
|
|
|
_generics: &ty::Generics<'tcx>,
|
2014-09-29 14:11:30 -05:00
|
|
|
substs: &Substs<'tcx>)
|
2014-08-27 20:46:52 -05:00
|
|
|
{
|
2015-02-13 18:52:55 -06:00
|
|
|
let predicates =
|
2015-06-25 15:42:17 -05:00
|
|
|
self.tcx().lookup_predicates(def_id).instantiate(self.tcx(), substs);
|
2015-02-13 18:52:55 -06:00
|
|
|
let predicates = match self.fully_normalize(&predicates) {
|
|
|
|
Ok(predicates) => predicates,
|
|
|
|
Err(ErrorReported) => { return; }
|
|
|
|
};
|
|
|
|
|
|
|
|
for predicate in predicates.predicates.as_slice() {
|
|
|
|
match *predicate {
|
|
|
|
ty::Predicate::Trait(ref data) => {
|
|
|
|
self.accumulate_from_assoc_types_transitive(data);
|
|
|
|
}
|
|
|
|
ty::Predicate::Equate(..) => { }
|
|
|
|
ty::Predicate::Projection(..) => { }
|
|
|
|
ty::Predicate::RegionOutlives(ref data) => {
|
2015-06-25 15:42:17 -05:00
|
|
|
match self.tcx().no_late_bound_regions(data) {
|
2015-02-13 18:52:55 -06:00
|
|
|
None => { }
|
|
|
|
Some(ty::OutlivesPredicate(r_a, r_b)) => {
|
|
|
|
self.push_sub_region_constraint(Some(ty), r_b, r_a);
|
|
|
|
}
|
2014-08-27 20:46:52 -05:00
|
|
|
}
|
|
|
|
}
|
2015-02-13 18:52:55 -06:00
|
|
|
ty::Predicate::TypeOutlives(ref data) => {
|
2015-06-25 15:42:17 -05:00
|
|
|
match self.tcx().no_late_bound_regions(data) {
|
2015-02-13 18:52:55 -06:00
|
|
|
None => { }
|
|
|
|
Some(ty::OutlivesPredicate(ty_a, r_b)) => {
|
|
|
|
self.stack.push((r_b, Some(ty)));
|
|
|
|
self.accumulate_from_ty(ty_a);
|
|
|
|
self.stack.pop().unwrap();
|
|
|
|
}
|
|
|
|
}
|
2013-04-02 00:32:37 -05:00
|
|
|
}
|
|
|
|
}
|
2015-02-13 18:52:55 -06:00
|
|
|
}
|
2014-08-27 20:46:52 -05:00
|
|
|
|
2015-02-13 18:52:55 -06:00
|
|
|
let obligations = predicates.predicates
|
|
|
|
.into_iter()
|
|
|
|
.map(|pred| Implication::Predicate(def_id, pred));
|
|
|
|
self.out.extend(obligations);
|
2014-08-27 20:46:52 -05:00
|
|
|
|
2015-06-25 15:42:17 -05:00
|
|
|
let variances = self.tcx().item_variances(def_id);
|
2015-02-13 18:52:55 -06:00
|
|
|
|
2015-06-10 11:22:20 -05:00
|
|
|
for (®ion, &variance) in substs.regions().iter().zip(&variances.regions) {
|
2015-02-13 18:52:55 -06:00
|
|
|
match variance {
|
|
|
|
ty::Contravariant | ty::Invariant => {
|
|
|
|
// If any data with this lifetime is reachable
|
|
|
|
// within, it must be at least contravariant.
|
|
|
|
self.push_region_constraint_from_top(region)
|
2014-08-27 20:46:52 -05:00
|
|
|
}
|
2015-02-13 18:52:55 -06:00
|
|
|
ty::Covariant | ty::Bivariant => { }
|
|
|
|
}
|
|
|
|
}
|
2014-08-27 20:46:52 -05:00
|
|
|
|
2015-06-10 11:22:20 -05:00
|
|
|
for (&ty, &variance) in substs.types.iter().zip(&variances.types) {
|
2015-02-13 18:52:55 -06:00
|
|
|
match variance {
|
|
|
|
ty::Covariant | ty::Invariant => {
|
|
|
|
// If any data of this type is reachable within,
|
|
|
|
// it must be at least covariant.
|
|
|
|
self.accumulate_from_ty(ty);
|
2014-08-27 20:46:52 -05:00
|
|
|
}
|
2015-02-13 18:52:55 -06:00
|
|
|
ty::Contravariant | ty::Bivariant => { }
|
2014-08-27 20:46:52 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-13 18:52:55 -06:00
|
|
|
/// Given that there is a requirement that `Foo<X> : 'a`, where
|
|
|
|
/// `Foo` is declared like `struct Foo<T> where T : SomeTrait`,
|
|
|
|
/// this code finds all the associated types defined in
|
|
|
|
/// `SomeTrait` (and supertraits) and adds a requirement that `<X
|
|
|
|
/// as SomeTrait>::N : 'a` (where `N` is some associated type
|
|
|
|
/// defined in `SomeTrait`). This rule only applies to
|
|
|
|
/// trait-bounds that are not higher-ranked, because we cannot
|
|
|
|
/// project out of a HRTB. This rule helps code using associated
|
|
|
|
/// types to compile, see Issue #22246 for an example.
|
|
|
|
fn accumulate_from_assoc_types_transitive(&mut self,
|
|
|
|
data: &ty::PolyTraitPredicate<'tcx>)
|
|
|
|
{
|
2015-06-18 12:25:05 -05:00
|
|
|
debug!("accumulate_from_assoc_types_transitive({:?})",
|
|
|
|
data);
|
2015-02-18 20:01:03 -06:00
|
|
|
|
2015-02-13 18:52:55 -06:00
|
|
|
for poly_trait_ref in traits::supertraits(self.tcx(), data.to_poly_trait_ref()) {
|
2015-06-25 15:42:17 -05:00
|
|
|
match self.tcx().no_late_bound_regions(&poly_trait_ref) {
|
2015-02-13 18:52:55 -06:00
|
|
|
Some(trait_ref) => { self.accumulate_from_assoc_types(trait_ref); }
|
|
|
|
None => { }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn accumulate_from_assoc_types(&mut self,
|
2015-04-21 10:59:58 -05:00
|
|
|
trait_ref: ty::TraitRef<'tcx>)
|
2015-02-13 18:52:55 -06:00
|
|
|
{
|
2015-06-18 12:25:05 -05:00
|
|
|
debug!("accumulate_from_assoc_types({:?})",
|
|
|
|
trait_ref);
|
2015-02-18 20:01:03 -06:00
|
|
|
|
2015-02-13 18:52:55 -06:00
|
|
|
let trait_def_id = trait_ref.def_id;
|
2015-06-25 15:42:17 -05:00
|
|
|
let trait_def = self.tcx().lookup_trait_def(trait_def_id);
|
2015-02-13 18:52:55 -06:00
|
|
|
let assoc_type_projections: Vec<_> =
|
|
|
|
trait_def.associated_type_names
|
|
|
|
.iter()
|
2015-06-24 20:09:46 -05:00
|
|
|
.map(|&name| self.tcx().mk_projection(trait_ref.clone(), name))
|
2015-02-13 18:52:55 -06:00
|
|
|
.collect();
|
2015-06-18 12:25:05 -05:00
|
|
|
debug!("accumulate_from_assoc_types: assoc_type_projections={:?}",
|
|
|
|
assoc_type_projections);
|
2015-02-13 18:52:55 -06:00
|
|
|
let tys = match self.fully_normalize(&assoc_type_projections) {
|
|
|
|
Ok(tys) => { tys }
|
|
|
|
Err(ErrorReported) => { return; }
|
|
|
|
};
|
|
|
|
for ty in tys {
|
|
|
|
self.accumulate_from_ty(ty);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-27 20:46:52 -05:00
|
|
|
fn accumulate_from_object_ty(&mut self,
|
2014-09-29 14:11:30 -05:00
|
|
|
ty: Ty<'tcx>,
|
2014-12-07 10:10:48 -06:00
|
|
|
region_bound: ty::Region,
|
|
|
|
required_region_bounds: Vec<ty::Region>)
|
2014-08-27 20:46:52 -05:00
|
|
|
{
|
|
|
|
// 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.
|
|
|
|
|
|
|
|
// The content of this object type must outlive
|
|
|
|
// `bounds.region_bound`:
|
2014-12-07 10:10:48 -06:00
|
|
|
let r_c = region_bound;
|
2014-08-27 20:46:52 -05:00
|
|
|
self.push_region_constraint_from_top(r_c);
|
|
|
|
|
|
|
|
// And then, in turn, to be well-formed, the
|
|
|
|
// `region_bound` that user specified must imply the
|
|
|
|
// region bounds required from all of the trait types:
|
2015-01-31 11:20:46 -06:00
|
|
|
for &r_d in &required_region_bounds {
|
2014-08-27 20:46:52 -05:00
|
|
|
// Each of these is an instance of the `'c <= 'b`
|
|
|
|
// constraint above
|
2015-02-04 09:48:29 -06:00
|
|
|
self.out.push(Implication::RegionSubRegion(Some(ty), r_d, r_c));
|
2014-08-27 20:46:52 -05:00
|
|
|
}
|
|
|
|
}
|
2015-02-13 18:52:55 -06:00
|
|
|
|
|
|
|
fn fully_normalize<T>(&self, value: &T) -> Result<T,ErrorReported>
|
2015-06-23 18:54:32 -05:00
|
|
|
where T : TypeFoldable<'tcx> + ty::HasTypeFlags
|
2015-02-13 18:52:55 -06:00
|
|
|
{
|
|
|
|
let value =
|
|
|
|
traits::fully_normalize(self.infcx,
|
|
|
|
traits::ObligationCause::misc(self.span, self.body_id),
|
|
|
|
value);
|
|
|
|
match value {
|
|
|
|
Ok(value) => Ok(value),
|
|
|
|
Err(errors) => {
|
|
|
|
// I don't like reporting these errors here, but I
|
|
|
|
// don't know where else to report them just now. And
|
|
|
|
// I don't really expect errors to arise here
|
|
|
|
// frequently. I guess the best option would be to
|
|
|
|
// propagate them out.
|
|
|
|
traits::report_fulfillment_errors(self.infcx, &errors);
|
|
|
|
Err(ErrorReported)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-04-10 15:11:27 -05:00
|
|
|
}
|
2014-11-25 19:15:58 -06:00
|
|
|
|
2015-04-18 10:23:14 -05:00
|
|
|
/// Given an object type like `SomeTrait+Send`, computes the lifetime
|
|
|
|
/// 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
|
|
|
|
/// `ty::required_region_bounds`, see that for more information.
|
|
|
|
pub fn object_region_bounds<'tcx>(
|
|
|
|
tcx: &ty::ctxt<'tcx>,
|
|
|
|
principal: &ty::PolyTraitRef<'tcx>,
|
|
|
|
others: ty::BuiltinBounds)
|
|
|
|
-> Vec<ty::Region>
|
|
|
|
{
|
|
|
|
// Since we don't actually *know* the self type for an object,
|
|
|
|
// this "open(err)" serves as a kind of dummy standin -- basically
|
|
|
|
// a skolemized type.
|
2015-06-24 20:09:46 -05:00
|
|
|
let open_ty = tcx.mk_infer(ty::FreshTy(0));
|
2015-04-18 10:23:14 -05:00
|
|
|
|
|
|
|
// Note that we preserve the overall binding levels here.
|
|
|
|
assert!(!open_ty.has_escaping_regions());
|
|
|
|
let substs = tcx.mk_substs(principal.0.substs.with_self_ty(open_ty));
|
2015-04-21 10:59:58 -05:00
|
|
|
let trait_refs = vec!(ty::Binder(ty::TraitRef::new(principal.0.def_id, substs)));
|
2015-04-18 10:23:14 -05:00
|
|
|
|
2015-06-16 17:53:13 -05:00
|
|
|
let mut predicates = others.to_predicates(tcx, open_ty);
|
2015-06-23 13:50:50 -05:00
|
|
|
predicates.extend(trait_refs.iter().map(|t| t.to_predicate()));
|
2015-04-18 10:23:14 -05:00
|
|
|
|
2015-06-25 15:42:17 -05:00
|
|
|
tcx.required_region_bounds(open_ty, predicates)
|
2015-04-18 10:23:14 -05:00
|
|
|
}
|