rustc: treat ReEarlyBound as free without replacing it with ReFree.
This commit is contained in:
parent
dbae169ac1
commit
2da080e779
35 changed files with 250 additions and 334 deletions
|
@ -54,7 +54,8 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::RegionKind<'tc
|
|||
db.depth.hash_stable(hcx, hasher);
|
||||
i.hash_stable(hcx, hasher);
|
||||
}
|
||||
ty::ReEarlyBound(ty::EarlyBoundRegion { index, name }) => {
|
||||
ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {
|
||||
def_id.hash_stable(hcx, hasher);
|
||||
index.hash_stable(hcx, hasher);
|
||||
name.hash_stable(hcx, hasher);
|
||||
}
|
||||
|
|
|
@ -423,15 +423,6 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
|
|||
return Ok(r);
|
||||
}
|
||||
|
||||
// Early-bound regions should really have been substituted away before
|
||||
// we get to this point.
|
||||
ty::ReEarlyBound(..) => {
|
||||
span_bug!(
|
||||
self.span,
|
||||
"Encountered early bound region when generalizing: {:?}",
|
||||
r);
|
||||
}
|
||||
|
||||
// Always make a fresh region variable for skolemized regions;
|
||||
// the higher-ranked decision procedures rely on this.
|
||||
ty::ReSkolemized(..) => { }
|
||||
|
@ -442,6 +433,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
|
|||
ty::ReStatic |
|
||||
ty::ReScope(..) |
|
||||
ty::ReVar(..) |
|
||||
ty::ReEarlyBound(..) |
|
||||
ty::ReFree(..) => {
|
||||
match self.ambient_variance {
|
||||
ty::Invariant => return Ok(r),
|
||||
|
|
|
@ -172,19 +172,35 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
explain_span(self, scope_decorated_tag, span)
|
||||
}
|
||||
|
||||
ty::ReFree(ref fr) => {
|
||||
let prefix = match fr.bound_region {
|
||||
ty::BrAnon(idx) => {
|
||||
format!("the anonymous lifetime #{} defined on", idx + 1)
|
||||
ty::ReEarlyBound(_) |
|
||||
ty::ReFree(_) => {
|
||||
let scope = match *region {
|
||||
ty::ReEarlyBound(ref br) => {
|
||||
self.parent_def_id(br.def_id).unwrap()
|
||||
}
|
||||
ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
|
||||
_ => {
|
||||
format!("the lifetime {} as defined on",
|
||||
fr.bound_region)
|
||||
ty::ReFree(ref fr) => fr.scope,
|
||||
_ => bug!()
|
||||
};
|
||||
let prefix = match *region {
|
||||
ty::ReEarlyBound(ref br) => {
|
||||
format!("the lifetime {} as defined on", br.name)
|
||||
}
|
||||
ty::ReFree(ref fr) => {
|
||||
match fr.bound_region {
|
||||
ty::BrAnon(idx) => {
|
||||
format!("the anonymous lifetime #{} defined on", idx + 1)
|
||||
}
|
||||
ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
|
||||
_ => {
|
||||
format!("the lifetime {} as defined on",
|
||||
fr.bound_region)
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => bug!()
|
||||
};
|
||||
|
||||
let node = self.hir.as_local_node_id(fr.scope)
|
||||
let node = self.hir.as_local_node_id(scope)
|
||||
.unwrap_or(DUMMY_NODE_ID);
|
||||
let unknown;
|
||||
let tag = match self.hir.find(node) {
|
||||
|
@ -199,12 +215,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
Some(_) => {
|
||||
unknown = format!("unexpected node ({}) for scope {:?}. \
|
||||
Please report a bug.",
|
||||
self.hir.node_to_string(node), fr.scope);
|
||||
self.hir.node_to_string(node), scope);
|
||||
&unknown
|
||||
}
|
||||
None => {
|
||||
unknown = format!("unknown node for scope {:?}. \
|
||||
Please report a bug.", fr.scope);
|
||||
Please report a bug.", scope);
|
||||
&unknown
|
||||
}
|
||||
};
|
||||
|
@ -216,8 +232,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
ty::ReEmpty => ("the empty lifetime".to_owned(), None),
|
||||
|
||||
ty::ReEarlyBound(ref data) => (data.name.to_string(), None),
|
||||
|
||||
// FIXME(#13998) ReSkolemized should probably print like
|
||||
// ReFree rather than dumping Debug output on the user.
|
||||
//
|
||||
|
@ -797,6 +811,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
let mut err = match *sub {
|
||||
ty::ReEarlyBound(_) |
|
||||
ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
|
||||
// Does the required lifetime have a nice name we can print?
|
||||
let mut err = struct_span_err!(self.tcx.sess,
|
||||
|
|
|
@ -85,13 +85,13 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
|
|||
|
||||
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
||||
match *r {
|
||||
ty::ReEarlyBound(..) |
|
||||
ty::ReLateBound(..) => {
|
||||
// leave bound regions alone
|
||||
r
|
||||
}
|
||||
|
||||
ty::ReStatic |
|
||||
ty::ReEarlyBound(..) |
|
||||
ty::ReFree(_) |
|
||||
ty::ReScope(_) |
|
||||
ty::ReVar(_) |
|
||||
|
|
|
@ -274,7 +274,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
|||
-> ty::Region<'tcx> {
|
||||
// Regions that pre-dated the LUB computation stay as they are.
|
||||
if !is_var_in_set(new_vars, r0) {
|
||||
assert!(!r0.is_bound());
|
||||
assert!(!r0.is_late_bound());
|
||||
debug!("generalize_region(r0={:?}): not new variable", r0);
|
||||
return r0;
|
||||
}
|
||||
|
@ -288,7 +288,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
|||
debug!("generalize_region(r0={:?}): \
|
||||
non-new-variables found in {:?}",
|
||||
r0, tainted);
|
||||
assert!(!r0.is_bound());
|
||||
assert!(!r0.is_late_bound());
|
||||
return r0;
|
||||
}
|
||||
|
||||
|
@ -371,7 +371,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
|||
r0: ty::Region<'tcx>)
|
||||
-> ty::Region<'tcx> {
|
||||
if !is_var_in_set(new_vars, r0) {
|
||||
assert!(!r0.is_bound());
|
||||
assert!(!r0.is_late_bound());
|
||||
return r0;
|
||||
}
|
||||
|
||||
|
@ -424,7 +424,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
|||
return rev_lookup(infcx, span, a_map, a_r.unwrap());
|
||||
} else if a_r.is_none() && b_r.is_none() {
|
||||
// Not related to bound variables from either fn:
|
||||
assert!(!r0.is_bound());
|
||||
assert!(!r0.is_late_bound());
|
||||
return r0;
|
||||
} else {
|
||||
// Other:
|
||||
|
|
|
@ -1009,7 +1009,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn add_given(&self,
|
||||
sub: ty::FreeRegion,
|
||||
sub: ty::Region<'tcx>,
|
||||
sup: ty::RegionVid)
|
||||
{
|
||||
self.region_vars.add_given(sub, sup);
|
||||
|
|
|
@ -29,7 +29,6 @@ use ty::{ReEmpty, ReStatic, ReFree, ReEarlyBound, ReErased};
|
|||
use ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::cmp::Ordering::{self, Less, Greater, Equal};
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::u32;
|
||||
|
@ -127,7 +126,7 @@ pub enum UndoLogEntry<'tcx> {
|
|||
AddVerify(usize),
|
||||
|
||||
/// We added the given `given`
|
||||
AddGiven(ty::FreeRegion, ty::RegionVid),
|
||||
AddGiven(Region<'tcx>, ty::RegionVid),
|
||||
|
||||
/// We added a GLB/LUB "combinaton variable"
|
||||
AddCombination(CombineMapType, TwoRegions<'tcx>),
|
||||
|
@ -213,7 +212,7 @@ pub struct RegionVarBindings<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
|||
// record the fact that `'a <= 'b` is implied by the fn signature,
|
||||
// and then ignore the constraint when solving equations. This is
|
||||
// a bit of a hack but seems to work.
|
||||
givens: RefCell<FxHashSet<(ty::FreeRegion, ty::RegionVid)>>,
|
||||
givens: RefCell<FxHashSet<(Region<'tcx>, ty::RegionVid)>>,
|
||||
|
||||
lubs: RefCell<CombineMap<'tcx>>,
|
||||
glbs: RefCell<CombineMap<'tcx>>,
|
||||
|
@ -309,8 +308,7 @@ impl<'a, 'gcx, 'tcx> TaintSet<'tcx> {
|
|||
self.add_edge(a, b);
|
||||
}
|
||||
&AddGiven(a, b) => {
|
||||
self.add_edge(tcx.mk_region(ReFree(a)),
|
||||
tcx.mk_region(ReVar(b)));
|
||||
self.add_edge(a, tcx.mk_region(ReVar(b)));
|
||||
}
|
||||
&AddVerify(i) => {
|
||||
verifys[i].bound.for_each_region(&mut |b| {
|
||||
|
@ -661,7 +659,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn add_given(&self, sub: ty::FreeRegion, sup: ty::RegionVid) {
|
||||
pub fn add_given(&self, sub: Region<'tcx>, sup: ty::RegionVid) {
|
||||
// cannot add givens once regions are resolved
|
||||
assert!(self.values_are_none());
|
||||
|
||||
|
@ -702,9 +700,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
|||
origin);
|
||||
|
||||
match (sub, sup) {
|
||||
(&ReEarlyBound(..), _) |
|
||||
(&ReLateBound(..), _) |
|
||||
(_, &ReEarlyBound(..)) |
|
||||
(_, &ReLateBound(..)) => {
|
||||
span_bug!(origin.span(),
|
||||
"cannot relate bound region: {:?} <= {:?}",
|
||||
|
@ -908,8 +904,6 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
|||
match (a, b) {
|
||||
(&ReLateBound(..), _) |
|
||||
(_, &ReLateBound(..)) |
|
||||
(&ReEarlyBound(..), _) |
|
||||
(_, &ReEarlyBound(..)) |
|
||||
(&ReErased, _) |
|
||||
(_, &ReErased) => {
|
||||
bug!("cannot relate region: LUB({:?}, {:?})", a, b);
|
||||
|
@ -931,18 +925,32 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
|||
b);
|
||||
}
|
||||
|
||||
(&ReFree(ref fr), &ReScope(s_id)) |
|
||||
(&ReScope(s_id), &ReFree(ref fr)) => {
|
||||
(&ReEarlyBound(_), &ReScope(s_id)) |
|
||||
(&ReScope(s_id), &ReEarlyBound(_)) |
|
||||
(&ReFree(_), &ReScope(s_id)) |
|
||||
(&ReScope(s_id), &ReFree(_)) => {
|
||||
// A "free" region can be interpreted as "some region
|
||||
// at least as big as fr.scope". So, we can
|
||||
// reasonably compare free regions and scopes:
|
||||
let fr_scope = region_rels.region_maps.free_extent(self.tcx, fr);
|
||||
let fr_scope = match (a, b) {
|
||||
(&ReEarlyBound(ref br), _) | (_, &ReEarlyBound(ref br)) => {
|
||||
region_rels.region_maps.early_free_extent(self.tcx, br)
|
||||
}
|
||||
(&ReFree(ref fr), _) | (_, &ReFree(ref fr)) => {
|
||||
region_rels.region_maps.free_extent(self.tcx, fr)
|
||||
}
|
||||
_ => bug!()
|
||||
};
|
||||
let r_id = region_rels.region_maps.nearest_common_ancestor(fr_scope, s_id);
|
||||
if r_id == fr_scope {
|
||||
// if the free region's scope `fr.scope` is bigger than
|
||||
// the scope region `s_id`, then the LUB is the free
|
||||
// region itself:
|
||||
return self.tcx.mk_region(ReFree(*fr));
|
||||
match (a, b) {
|
||||
(_, &ReScope(_)) => return a,
|
||||
(&ReScope(_), _) => return b,
|
||||
_ => bug!()
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise, we don't know what the free region is,
|
||||
|
@ -958,6 +966,9 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
|||
self.tcx.mk_region(ReScope(lub))
|
||||
}
|
||||
|
||||
(&ReEarlyBound(_), &ReEarlyBound(_)) |
|
||||
(&ReFree(_), &ReEarlyBound(_)) |
|
||||
(&ReEarlyBound(_), &ReFree(_)) |
|
||||
(&ReFree(_), &ReFree(_)) => {
|
||||
region_rels.lub_free_regions(a, b)
|
||||
}
|
||||
|
@ -1040,13 +1051,13 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
|||
|
||||
let mut givens = self.givens.borrow_mut();
|
||||
let seeds: Vec<_> = givens.iter().cloned().collect();
|
||||
for (fr, vid) in seeds {
|
||||
for (r, vid) in seeds {
|
||||
let seed_index = NodeIndex(vid.index as usize);
|
||||
for succ_index in graph.depth_traverse(seed_index, OUTGOING) {
|
||||
let succ_index = succ_index.0 as u32;
|
||||
if succ_index < self.num_vars() {
|
||||
let succ_vid = RegionVid { index: succ_index };
|
||||
givens.insert((fr, succ_vid));
|
||||
givens.insert((r, succ_vid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1095,8 +1106,9 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
|||
|
||||
// Check if this relationship is implied by a given.
|
||||
match *a_region {
|
||||
ty::ReFree(fr) => {
|
||||
if self.givens.borrow().contains(&(fr, b_vid)) {
|
||||
ty::ReEarlyBound(_) |
|
||||
ty::ReFree(_) => {
|
||||
if self.givens.borrow().contains(&(a_region, b_vid)) {
|
||||
debug!("given");
|
||||
return false;
|
||||
}
|
||||
|
@ -1332,16 +1344,15 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
|||
// We place free regions first because we are special casing
|
||||
// SubSupConflict(ReFree, ReFree) when reporting error, and so
|
||||
// the user will more likely get a specific suggestion.
|
||||
fn free_regions_first(a: &RegionAndOrigin, b: &RegionAndOrigin) -> Ordering {
|
||||
match (a.region, b.region) {
|
||||
(&ReFree(..), &ReFree(..)) => Equal,
|
||||
(&ReFree(..), _) => Less,
|
||||
(_, &ReFree(..)) => Greater,
|
||||
(..) => Equal,
|
||||
fn region_order_key(x: &RegionAndOrigin) -> u8 {
|
||||
match *x.region {
|
||||
ReEarlyBound(_) => 0,
|
||||
ReFree(_) => 1,
|
||||
_ => 2
|
||||
}
|
||||
}
|
||||
lower_bounds.sort_by(|a, b| free_regions_first(a, b));
|
||||
upper_bounds.sort_by(|a, b| free_regions_first(a, b));
|
||||
lower_bounds.sort_by_key(region_order_key);
|
||||
upper_bounds.sort_by_key(region_order_key);
|
||||
|
||||
for lower_bound in &lower_bounds {
|
||||
for upper_bound in &upper_bounds {
|
||||
|
|
|
@ -71,23 +71,27 @@ impl<'a, 'gcx, 'tcx> RegionRelations<'a, 'gcx, 'tcx> {
|
|||
(&ty::ReScope(sub_scope), &ty::ReScope(super_scope)) =>
|
||||
self.region_maps.is_subscope_of(sub_scope, super_scope),
|
||||
|
||||
(&ty::ReScope(sub_scope), &ty::ReFree(ref fr)) => {
|
||||
let fr_scope = self.region_maps.free_extent(self.tcx, fr);
|
||||
self.region_maps.is_subscope_of(sub_scope, fr_scope) ||
|
||||
self.is_static(super_region)
|
||||
(&ty::ReScope(sub_scope), &ty::ReEarlyBound(ref br)) => {
|
||||
let fr_scope = self.region_maps.early_free_extent(self.tcx, br);
|
||||
self.region_maps.is_subscope_of(sub_scope, fr_scope)
|
||||
}
|
||||
|
||||
(&ty::ReFree(_), &ty::ReFree(_)) =>
|
||||
self.free_regions.relation.contains(&sub_region, &super_region) ||
|
||||
self.is_static(super_region),
|
||||
(&ty::ReScope(sub_scope), &ty::ReFree(ref fr)) => {
|
||||
let fr_scope = self.region_maps.free_extent(self.tcx, fr);
|
||||
self.region_maps.is_subscope_of(sub_scope, fr_scope)
|
||||
}
|
||||
|
||||
(&ty::ReStatic, &ty::ReFree(_)) =>
|
||||
self.is_static(super_region),
|
||||
(&ty::ReEarlyBound(_), &ty::ReEarlyBound(_)) |
|
||||
(&ty::ReFree(_), &ty::ReEarlyBound(_)) |
|
||||
(&ty::ReEarlyBound(_), &ty::ReFree(_)) |
|
||||
(&ty::ReFree(_), &ty::ReFree(_)) =>
|
||||
self.free_regions.relation.contains(&sub_region, &super_region),
|
||||
|
||||
_ =>
|
||||
false,
|
||||
}
|
||||
};
|
||||
let result = result || self.is_static(super_region);
|
||||
debug!("is_subregion_of(sub_region={:?}, super_region={:?}) = {:?}",
|
||||
sub_region, super_region, result);
|
||||
result
|
||||
|
@ -98,11 +102,11 @@ impl<'a, 'gcx, 'tcx> RegionRelations<'a, 'gcx, 'tcx> {
|
|||
debug!("is_static(super_region={:?})", super_region);
|
||||
match *super_region {
|
||||
ty::ReStatic => true,
|
||||
ty::ReFree(_) => {
|
||||
ty::ReEarlyBound(_) | ty::ReFree(_) => {
|
||||
let re_static = self.tcx.mk_region(ty::ReStatic);
|
||||
self.free_regions.relation.contains(&re_static, &super_region)
|
||||
}
|
||||
_ => bug!("only free regions should be given to `is_static`")
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,11 +143,9 @@ impl<'tcx> FreeRegionMap<'tcx> {
|
|||
for implied_bound in implied_bounds {
|
||||
debug!("implied bound: {:?}", implied_bound);
|
||||
match *implied_bound {
|
||||
ImpliedBound::RegionSubRegion(a @ &ty::ReFree(_), b @ &ty::ReFree(_)) |
|
||||
ImpliedBound::RegionSubRegion(a @ &ty::ReStatic, b @ &ty::ReFree(_)) => {
|
||||
ImpliedBound::RegionSubRegion(a, b) => {
|
||||
self.relate_regions(a, b);
|
||||
}
|
||||
ImpliedBound::RegionSubRegion(..) |
|
||||
ImpliedBound::RegionSubParam(..) |
|
||||
ImpliedBound::RegionSubProjection(..) => {
|
||||
}
|
||||
|
@ -167,32 +169,18 @@ impl<'tcx> FreeRegionMap<'tcx> {
|
|||
// No region bounds here
|
||||
}
|
||||
ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r_a, r_b))) => {
|
||||
match (r_a, r_b) {
|
||||
// `'static: 'x` is not notable
|
||||
(&ty::ReStatic, &ty::ReFree(_)) => {},
|
||||
|
||||
(&ty::ReFree(_), &ty::ReStatic) |
|
||||
(&ty::ReFree(_), &ty::ReFree(_)) => {
|
||||
// Record that `'a:'b`. Or, put another way, `'b <= 'a`.
|
||||
self.relate_regions(r_b, r_a);
|
||||
}
|
||||
|
||||
_ => {
|
||||
// All named regions are instantiated with free regions.
|
||||
bug!("record_region_bounds: non free region: {:?} / {:?}",
|
||||
r_a,
|
||||
r_b);
|
||||
}
|
||||
}
|
||||
self.relate_regions(r_b, r_a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Record that `'sup:'sub`. Or, put another way, `'sub <= 'sup`.
|
||||
// (with the exception that `'static: 'x` is not notable)
|
||||
fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) {
|
||||
assert!(match *sub { ty::ReFree(_) | ty::ReStatic => true, _ => false });
|
||||
assert!(match *sup { ty::ReFree(_) | ty::ReStatic => true, _ => false });
|
||||
self.relation.add(sub, sup)
|
||||
if (is_free(sub) || *sub == ty::ReStatic) && is_free(sup) {
|
||||
self.relation.add(sub, sup)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lub_free_regions<'a, 'gcx>(&self,
|
||||
|
@ -200,8 +188,8 @@ impl<'tcx> FreeRegionMap<'tcx> {
|
|||
r_a: Region<'tcx>,
|
||||
r_b: Region<'tcx>)
|
||||
-> Region<'tcx> {
|
||||
assert!(match *r_a { ty::ReFree(_) => true, _ => false });
|
||||
assert!(match *r_b { ty::ReFree(_) => true, _ => false });
|
||||
assert!(is_free(r_a));
|
||||
assert!(is_free(r_b));
|
||||
let result = if r_a == r_b { r_a } else {
|
||||
match self.relation.postdom_upper_bound(&r_a, &r_b) {
|
||||
None => tcx.mk_region(ty::ReStatic),
|
||||
|
@ -213,6 +201,13 @@ impl<'tcx> FreeRegionMap<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_free(r: Region) -> bool {
|
||||
match *r {
|
||||
ty::ReEarlyBound(_) | ty::ReFree(_) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct FreeRegionMap<'tcx> {
|
||||
relation
|
||||
});
|
||||
|
|
|
@ -606,6 +606,33 @@ impl<'tcx> RegionMaps<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Assuming that the provided region was defined within this `RegionMaps`,
|
||||
/// returns the outermost `CodeExtent` that the region outlives.
|
||||
pub fn early_free_extent<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
br: &ty::EarlyBoundRegion)
|
||||
-> CodeExtent<'tcx> {
|
||||
let param_owner = tcx.parent_def_id(br.def_id).unwrap();
|
||||
|
||||
let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap();
|
||||
let body_id = tcx.hir.maybe_body_owned_by(param_owner_id).unwrap_or_else(|| {
|
||||
// The lifetime was defined on node that doesn't own a body,
|
||||
// which in practice can only mean a trait or an impl, that
|
||||
// is the parent of a method, and that is enforced below.
|
||||
assert_eq!(Some(param_owner_id), self.root_parent,
|
||||
"free_extent: {:?} not recognized by the region maps for {:?}",
|
||||
param_owner,
|
||||
self.root_body.map(|body| tcx.hir.body_owner_def_id(body)));
|
||||
|
||||
// The trait/impl lifetime is in scope for the method's body.
|
||||
self.root_body.unwrap()
|
||||
});
|
||||
|
||||
tcx.intern_code_extent(CodeExtentData::CallSiteScope {
|
||||
fn_id: tcx.hir.body_owner(body_id),
|
||||
body_id: body_id.node_id
|
||||
})
|
||||
}
|
||||
|
||||
/// Assuming that the provided region was defined within this `RegionMaps`,
|
||||
/// returns the outermost `CodeExtent` that the region outlives.
|
||||
pub fn free_extent<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, fr: &ty::FreeRegion)
|
||||
|
@ -617,27 +644,12 @@ impl<'tcx> RegionMaps<'tcx> {
|
|||
_ => fr.scope
|
||||
};
|
||||
|
||||
// Ensure that the named late-bound lifetimes were defined
|
||||
// on the same function that they ended up being freed in.
|
||||
assert_eq!(param_owner, fr.scope);
|
||||
|
||||
let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap();
|
||||
let body_id = tcx.hir.maybe_body_owned_by(param_owner_id)
|
||||
.map(|body| {
|
||||
assert_eq!(param_owner, fr.scope);
|
||||
body
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
let root = tcx.hir.as_local_node_id(fr.scope).unwrap();
|
||||
|
||||
assert_eq!(Some(param_owner_id), self.root_parent,
|
||||
"free_extent: {:?} not recognized by the region maps for {:?}",
|
||||
param_owner, fr.scope);
|
||||
|
||||
let root_body = tcx.hir.body_owned_by(root);
|
||||
|
||||
assert!(Some(root_body) == self.root_body,
|
||||
"free_extent: {:?} not inside {:?}",
|
||||
param_owner, self.root_body.map(|body| tcx.hir.body_owner_def_id(body)));
|
||||
|
||||
root_body
|
||||
});
|
||||
let body_id = tcx.hir.body_owned_by(param_owner_id);
|
||||
|
||||
tcx.intern_code_extent(CodeExtentData::CallSiteScope {
|
||||
fn_id: tcx.hir.body_owner(body_id),
|
||||
|
|
|
@ -894,7 +894,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
};
|
||||
|
||||
if let Some(mut def) = result {
|
||||
if let Some(body_id) = outermost_body {
|
||||
if let Region::EarlyBound(..) = def {
|
||||
// Do not free early-bound regions, only late-bound ones.
|
||||
} else if let Some(body_id) = outermost_body {
|
||||
let fn_id = self.hir_map.body_owner(body_id);
|
||||
match self.hir_map.get(fn_id) {
|
||||
hir::map::NodeItem(&hir::Item {
|
||||
|
|
|
@ -206,9 +206,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
};
|
||||
|
||||
// Search for a predicate like `Self : Sized` amongst the trait bounds.
|
||||
let free_substs = self.construct_free_substs(def_id);
|
||||
let predicates = self.predicates_of(def_id);
|
||||
let predicates = predicates.instantiate(self, free_substs).predicates;
|
||||
let predicates = predicates.instantiate_identity(self).predicates;
|
||||
elaborate_predicates(self, predicates)
|
||||
.any(|predicate| {
|
||||
match predicate {
|
||||
|
|
|
@ -180,9 +180,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|
||||
// create a parameter environment corresponding to a (skolemized) instantiation of impl1
|
||||
let penv = tcx.parameter_environment(impl1_def_id);
|
||||
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id)
|
||||
.unwrap()
|
||||
.subst(tcx, &penv.free_substs);
|
||||
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
|
||||
|
||||
// Create a infcx, taking the predicates of impl1 as assumptions:
|
||||
let result = tcx.infer_ctxt(penv, Reveal::UserFacing).enter(|infcx| {
|
||||
|
|
|
@ -197,7 +197,7 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
|
|||
// I want to be conservative. --nmatsakis
|
||||
let ty_max = data.skip_binder().0;
|
||||
let r_min = data.skip_binder().1;
|
||||
if r_min.is_bound() {
|
||||
if r_min.is_late_bound() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -206,7 +206,7 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
|
|||
tcx.outlives_components(ty_max)
|
||||
.into_iter()
|
||||
.filter_map(|component| match component {
|
||||
Component::Region(r) => if r.is_bound() {
|
||||
Component::Region(r) => if r.is_late_bound() {
|
||||
None
|
||||
} else {
|
||||
Some(ty::Predicate::RegionOutlives(
|
||||
|
|
|
@ -1271,7 +1271,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
|||
let param_env = tcx.parameter_environment(def.did);
|
||||
let fields = &def.variants[0].fields;
|
||||
let last_field = &fields[fields.len()-1];
|
||||
let always_sized = last_field.ty(tcx, param_env.free_substs)
|
||||
let always_sized = tcx.type_of(last_field.did)
|
||||
.is_sized(tcx, ¶m_env, DUMMY_SP);
|
||||
if !always_sized { StructKind::MaybeUnsizedUnivariant }
|
||||
else { StructKind::AlwaysSizedUnivariant }
|
||||
|
|
|
@ -731,11 +731,18 @@ pub struct RegionParameterDef {
|
|||
impl RegionParameterDef {
|
||||
pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
|
||||
ty::EarlyBoundRegion {
|
||||
def_id: self.def_id,
|
||||
index: self.index,
|
||||
name: self.name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_bound_region(&self) -> ty::BoundRegion {
|
||||
self.to_early_bound_region_data().to_bound_region()
|
||||
}
|
||||
}
|
||||
|
||||
impl ty::EarlyBoundRegion {
|
||||
pub fn to_bound_region(&self) -> ty::BoundRegion {
|
||||
ty::BoundRegion::BrNamed(self.def_id, self.name)
|
||||
}
|
||||
|
@ -815,6 +822,21 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
|
|||
instantiated.predicates.extend(self.predicates.iter().map(|p| p.subst(tcx, substs)))
|
||||
}
|
||||
|
||||
pub fn instantiate_identity(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
|
||||
-> InstantiatedPredicates<'tcx> {
|
||||
let mut instantiated = InstantiatedPredicates::empty();
|
||||
self.instantiate_identity_into(tcx, &mut instantiated);
|
||||
instantiated
|
||||
}
|
||||
|
||||
fn instantiate_identity_into(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
instantiated: &mut InstantiatedPredicates<'tcx>) {
|
||||
if let Some(def_id) = self.parent {
|
||||
tcx.predicates_of(def_id).instantiate_identity_into(tcx, instantiated);
|
||||
}
|
||||
instantiated.predicates.extend(&self.predicates)
|
||||
}
|
||||
|
||||
pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
poly_trait_ref: &ty::PolyTraitRef<'tcx>)
|
||||
-> InstantiatedPredicates<'tcx>
|
||||
|
@ -1240,9 +1262,6 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
|
|||
/// more distinctions clearer.
|
||||
#[derive(Clone)]
|
||||
pub struct ParameterEnvironment<'tcx> {
|
||||
/// See `construct_free_substs` for details.
|
||||
pub free_substs: &'tcx Substs<'tcx>,
|
||||
|
||||
/// Obligations that the caller must satisfy. This is basically
|
||||
/// the set of bounds on the in-scope type parameters, translated
|
||||
/// into Obligations, and elaborated and normalized.
|
||||
|
@ -1264,7 +1283,6 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
|
|||
-> ParameterEnvironment<'tcx>
|
||||
{
|
||||
ParameterEnvironment {
|
||||
free_substs: self.free_substs,
|
||||
caller_bounds: caller_bounds,
|
||||
is_copy_cache: RefCell::new(FxHashMap()),
|
||||
is_sized_cache: RefCell::new(FxHashMap()),
|
||||
|
@ -2372,7 +2390,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
/// are no free type/lifetime parameters in scope.
|
||||
pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
|
||||
ty::ParameterEnvironment {
|
||||
free_substs: self.intern_substs(&[]),
|
||||
caller_bounds: Slice::empty(),
|
||||
is_copy_cache: RefCell::new(FxHashMap()),
|
||||
is_sized_cache: RefCell::new(FxHashMap()),
|
||||
|
@ -2380,43 +2397,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Constructs and returns a substitution that can be applied to move from
|
||||
/// the "outer" view of a type or method to the "inner" view.
|
||||
/// In general, this means converting from bound parameters to
|
||||
/// free parameters. Since we currently represent bound/free type
|
||||
/// parameters in the same way, this only has an effect on regions.
|
||||
pub fn construct_free_substs(self, def_id: DefId) -> &'gcx Substs<'gcx> {
|
||||
let scope = self.closure_base_def_id(def_id);
|
||||
let substs = Substs::for_item(self.global_tcx(), def_id, |def, _| {
|
||||
// map bound 'a => free 'a
|
||||
self.global_tcx().mk_region(ReFree(FreeRegion {
|
||||
scope,
|
||||
bound_region: def.to_bound_region()
|
||||
}))
|
||||
}, |def, _| {
|
||||
// map T => T
|
||||
self.global_tcx().mk_param_from_def(def)
|
||||
});
|
||||
|
||||
debug!("parameter_environment: {:?}", substs);
|
||||
substs
|
||||
}
|
||||
|
||||
/// See `ParameterEnvironment` struct def'n for details.
|
||||
pub fn parameter_environment(self, def_id: DefId) -> ParameterEnvironment<'gcx> {
|
||||
//
|
||||
// Construct the free substs.
|
||||
//
|
||||
|
||||
let free_substs = self.construct_free_substs(def_id);
|
||||
|
||||
//
|
||||
// Compute the bounds on Self and the type parameters.
|
||||
//
|
||||
|
||||
let tcx = self.global_tcx();
|
||||
let generic_predicates = tcx.predicates_of(def_id);
|
||||
let bounds = generic_predicates.instantiate(tcx, free_substs);
|
||||
let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
|
||||
let predicates = bounds.predicates;
|
||||
|
||||
// Finally, we have to normalize the bounds in the environment, in
|
||||
|
@ -2433,7 +2421,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
//
|
||||
|
||||
let unnormalized_env = ty::ParameterEnvironment {
|
||||
free_substs,
|
||||
caller_bounds: tcx.intern_predicates(&predicates),
|
||||
is_copy_cache: RefCell::new(FxHashMap()),
|
||||
is_sized_cache: RefCell::new(FxHashMap()),
|
||||
|
|
|
@ -204,7 +204,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
fn push_region_constraints<'tcx>(out: &mut Vec<Component<'tcx>>, regions: Vec<ty::Region<'tcx>>) {
|
||||
for r in regions {
|
||||
if !r.is_bound() {
|
||||
if !r.is_late_bound() {
|
||||
out.push(Component::Region(r));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -790,6 +790,7 @@ impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {}
|
|||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct EarlyBoundRegion {
|
||||
pub def_id: DefId,
|
||||
pub index: u32,
|
||||
pub name: Name,
|
||||
}
|
||||
|
@ -906,9 +907,8 @@ impl DebruijnIndex {
|
|||
|
||||
/// Region utilities
|
||||
impl<'tcx> RegionKind<'tcx> {
|
||||
pub fn is_bound(&self) -> bool {
|
||||
pub fn is_late_bound(&self) -> bool {
|
||||
match *self {
|
||||
ty::ReEarlyBound(..) => true,
|
||||
ty::ReLateBound(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
|
|
|
@ -688,9 +688,8 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W>
|
|||
self.hash(db.depth);
|
||||
self.hash(i);
|
||||
}
|
||||
ty::ReEarlyBound(ty::EarlyBoundRegion { index, name }) => {
|
||||
self.hash(index);
|
||||
self.hash(name.as_str());
|
||||
ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, .. }) => {
|
||||
self.def_id(def_id);
|
||||
}
|
||||
ty::ReLateBound(..) |
|
||||
ty::ReFree(..) |
|
||||
|
|
|
@ -506,11 +506,7 @@ impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> {
|
|||
|
||||
impl<'tcx> fmt::Debug for ty::ParameterEnvironment<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "ParameterEnvironment(\
|
||||
free_substs={:?}, \
|
||||
caller_bounds={:?})",
|
||||
self.free_substs,
|
||||
self.caller_bounds)
|
||||
write!(f, "ParameterEnvironment({:?})", self.caller_bounds)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -353,6 +353,10 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
|
|||
let loan_scope = match *loan_region {
|
||||
ty::ReScope(scope) => scope,
|
||||
|
||||
ty::ReEarlyBound(ref br) => {
|
||||
self.bccx.region_maps.early_free_extent(self.tcx(), br)
|
||||
}
|
||||
|
||||
ty::ReFree(ref fr) => {
|
||||
self.bccx.region_maps.free_extent(self.tcx(), fr)
|
||||
}
|
||||
|
@ -361,7 +365,6 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
|
|||
|
||||
ty::ReEmpty |
|
||||
ty::ReLateBound(..) |
|
||||
ty::ReEarlyBound(..) |
|
||||
ty::ReVar(..) |
|
||||
ty::ReSkolemized(..) |
|
||||
ty::ReErased => {
|
||||
|
|
|
@ -513,6 +513,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
|||
match (&err.code, &err.cause) {
|
||||
(&err_out_of_scope(&ty::ReScope(_), &ty::ReStatic, _),
|
||||
&BorrowViolation(euv::ClosureCapture(span))) |
|
||||
(&err_out_of_scope(&ty::ReScope(_), &ty::ReEarlyBound(..), _),
|
||||
&BorrowViolation(euv::ClosureCapture(span))) |
|
||||
(&err_out_of_scope(&ty::ReScope(_), &ty::ReFree(..), _),
|
||||
&BorrowViolation(euv::ClosureCapture(span))) => {
|
||||
return self.report_out_of_scope_escaping_closure_capture(&err, span);
|
||||
|
|
|
@ -296,8 +296,9 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
|
|||
pub fn re_early_bound(&self, index: u32, name: &'static str) -> ty::Region<'tcx> {
|
||||
let name = Symbol::intern(name);
|
||||
self.infcx.tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
|
||||
index: index,
|
||||
name: name,
|
||||
def_id: self.infcx.tcx.hir.local_def_id(ast::CRATE_NODE_ID),
|
||||
index,
|
||||
name,
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ use rustc::middle::const_val::ConstVal;
|
|||
use rustc::mir::*;
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::subst::{Kind, Subst};
|
||||
use rustc::ty::subst::{Kind, Subst, Substs};
|
||||
use rustc::ty::maps::Providers;
|
||||
|
||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
|
@ -65,7 +65,6 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|
||||
build_call_shim(
|
||||
tcx,
|
||||
¶m_env,
|
||||
def_id,
|
||||
adjustment,
|
||||
CallKind::Indirect,
|
||||
|
@ -77,7 +76,6 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
|||
// trans::mir knows to turn to an actual virtual call.
|
||||
build_call_shim(
|
||||
tcx,
|
||||
¶m_env,
|
||||
def_id,
|
||||
Adjustment::Identity,
|
||||
CallKind::Direct(def_id),
|
||||
|
@ -93,7 +91,6 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|
||||
build_call_shim(
|
||||
tcx,
|
||||
¶m_env,
|
||||
call_once,
|
||||
Adjustment::RefMut,
|
||||
CallKind::Direct(call_mut),
|
||||
|
@ -157,7 +154,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let substs = if let Some(ty) = ty {
|
||||
tcx.mk_substs(iter::once(Kind::from(ty)))
|
||||
} else {
|
||||
param_env.free_substs
|
||||
Substs::identity_for_item(tcx, def_id)
|
||||
};
|
||||
let fn_ty = tcx.type_of(def_id).subst(tcx, substs);
|
||||
let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
|
||||
|
@ -271,7 +268,6 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
|
|||
/// If `untuple_args` is a vec of types, the second argument of the
|
||||
/// function will be untupled as these types.
|
||||
fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
||||
param_env: &ty::ParameterEnvironment<'tcx>,
|
||||
def_id: DefId,
|
||||
rcvr_adjustment: Adjustment,
|
||||
call_kind: CallKind,
|
||||
|
@ -282,7 +278,7 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
|||
call_kind={:?}, untuple_args={:?})",
|
||||
def_id, rcvr_adjustment, call_kind, untuple_args);
|
||||
|
||||
let fn_ty = tcx.type_of(def_id).subst(tcx, param_env.free_substs);
|
||||
let fn_ty = tcx.type_of(def_id);
|
||||
let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
|
||||
let span = tcx.def_span(def_id);
|
||||
|
||||
|
@ -324,9 +320,10 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
|||
CallKind::Direct(def_id) => (
|
||||
Operand::Constant(box Constant {
|
||||
span: span,
|
||||
ty: tcx.type_of(def_id).subst(tcx, param_env.free_substs),
|
||||
ty: tcx.type_of(def_id),
|
||||
literal: Literal::Value {
|
||||
value: ConstVal::Function(def_id, param_env.free_substs),
|
||||
value: ConstVal::Function(def_id,
|
||||
Substs::identity_for_item(tcx, def_id)),
|
||||
},
|
||||
}),
|
||||
vec![rcvr]
|
||||
|
|
|
@ -41,12 +41,6 @@ pub trait AstConv<'gcx, 'tcx> {
|
|||
fn get_type_parameter_bounds(&self, span: Span, def_id: DefId)
|
||||
-> ty::GenericPredicates<'tcx>;
|
||||
|
||||
/// Return an (optional) substitution to convert bound type parameters that
|
||||
/// are in scope into free ones. This function should only return Some
|
||||
/// within a fn body.
|
||||
/// See ParameterEnvironment::free_substs for more information.
|
||||
fn get_free_substs(&self) -> Option<&Substs<'tcx>>;
|
||||
|
||||
/// What lifetime should we use when a lifetime is omitted (and not elided)?
|
||||
fn re_infer(&self, span: Span, _def: Option<&ty::RegionParameterDef>)
|
||||
-> Option<ty::Region<'tcx>>;
|
||||
|
@ -121,6 +115,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
Some(&rl::Region::EarlyBound(index, id)) => {
|
||||
let name = tcx.hir.name(id);
|
||||
tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
|
||||
def_id: tcx.hir.local_def_id(id),
|
||||
index: index,
|
||||
name: name
|
||||
}))
|
||||
|
@ -857,12 +852,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
}
|
||||
};
|
||||
|
||||
let trait_ref = if let Some(free_substs) = self.get_free_substs() {
|
||||
trait_ref.subst(tcx, free_substs)
|
||||
} else {
|
||||
trait_ref
|
||||
};
|
||||
|
||||
let candidates =
|
||||
traits::supertraits(tcx, ty::Binder(trait_ref))
|
||||
.filter(|r| self.trait_defines_associated_type_named(r.def_id(),
|
||||
|
@ -1020,12 +1009,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
assert_eq!(opt_self_ty, None);
|
||||
self.prohibit_type_params(&path.segments);
|
||||
|
||||
let ty = tcx.at(span).type_of(def_id);
|
||||
if let Some(free_substs) = self.get_free_substs() {
|
||||
ty.subst(tcx, free_substs)
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
tcx.at(span).type_of(def_id)
|
||||
}
|
||||
Def::SelfTy(Some(_), None) => {
|
||||
// Self in trait.
|
||||
|
|
|
@ -15,6 +15,7 @@ use super::{check_fn, Expectation, FnCtxt};
|
|||
use astconv::AstConv;
|
||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||
use rustc::ty::{self, ToPolyTraitRef, Ty};
|
||||
use rustc::ty::subst::Substs;
|
||||
use std::cmp;
|
||||
use std::iter;
|
||||
use syntax::abi::Abi;
|
||||
|
@ -67,8 +68,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// Create type variables (for now) to represent the transformed
|
||||
// types of upvars. These will be unified during the upvar
|
||||
// inference phase (`upvar.rs`).
|
||||
let base_substs = Substs::identity_for_item(self.tcx,
|
||||
self.tcx.closure_base_def_id(expr_def_id));
|
||||
let closure_type = self.tcx.mk_closure(expr_def_id,
|
||||
self.parameter_environment.free_substs.extend_to(self.tcx, expr_def_id,
|
||||
base_substs.extend_to(self.tcx, expr_def_id,
|
||||
|_, _| span_bug!(expr.span, "closure has region param"),
|
||||
|_, _| self.infcx.next_ty_var(TypeVariableOrigin::TransformedUpvar(expr.span))
|
||||
)
|
||||
|
|
|
@ -170,13 +170,12 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let impl_param_env = tcx.parameter_environment(impl_m.def_id);
|
||||
|
||||
// Create mapping from impl to skolemized.
|
||||
let impl_to_skol_substs = &impl_param_env.free_substs;
|
||||
let impl_to_skol_substs = Substs::identity_for_item(tcx, impl_m.def_id);
|
||||
|
||||
// Create mapping from trait to skolemized.
|
||||
let trait_to_skol_substs = impl_to_skol_substs.rebase_onto(tcx,
|
||||
impl_m.container.id(),
|
||||
trait_to_impl_substs.subst(tcx,
|
||||
impl_to_skol_substs));
|
||||
trait_to_impl_substs);
|
||||
debug!("compare_impl_method: trait_to_skol_substs={:?}",
|
||||
trait_to_skol_substs);
|
||||
|
||||
|
@ -191,8 +190,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
impl_m,
|
||||
&trait_m_generics,
|
||||
&impl_m_generics,
|
||||
trait_to_skol_substs,
|
||||
impl_to_skol_substs)?;
|
||||
trait_to_skol_substs)?;
|
||||
|
||||
// Create obligations for each predicate declared by the impl
|
||||
// definition in the context of the trait's parameter
|
||||
|
@ -200,7 +198,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
// however, because we want to replace all late-bound regions with
|
||||
// region variables.
|
||||
let impl_predicates = tcx.predicates_of(impl_m_predicates.parent.unwrap());
|
||||
let mut hybrid_preds = impl_predicates.instantiate(tcx, impl_to_skol_substs);
|
||||
let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
|
||||
|
||||
debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds);
|
||||
|
||||
|
@ -273,8 +271,6 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
|
||||
infer::HigherRankedType,
|
||||
&m_sig(impl_m));
|
||||
let impl_sig =
|
||||
impl_sig.subst(tcx, impl_to_skol_substs);
|
||||
let impl_sig =
|
||||
inh.normalize_associated_types_in(impl_m_span,
|
||||
impl_m_node_id,
|
||||
|
@ -370,8 +366,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
impl_m: &ty::AssociatedItem,
|
||||
trait_generics: &ty::Generics,
|
||||
impl_generics: &ty::Generics,
|
||||
trait_to_skol_substs: &Substs<'tcx>,
|
||||
impl_to_skol_substs: &Substs<'tcx>)
|
||||
trait_to_skol_substs: &Substs<'tcx>)
|
||||
-> Result<(), ErrorReported> {
|
||||
let trait_params = &trait_generics.regions[..];
|
||||
let impl_params = &impl_generics.regions[..];
|
||||
|
@ -379,12 +374,10 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
debug!("check_region_bounds_on_impl_method: \
|
||||
trait_generics={:?} \
|
||||
impl_generics={:?} \
|
||||
trait_to_skol_substs={:?} \
|
||||
impl_to_skol_substs={:?}",
|
||||
trait_to_skol_substs={:?}",
|
||||
trait_generics,
|
||||
impl_generics,
|
||||
trait_to_skol_substs,
|
||||
impl_to_skol_substs);
|
||||
trait_to_skol_substs);
|
||||
|
||||
// Must have same number of early-bound lifetime parameters.
|
||||
// Unfortunately, if the user screws up the bounds, then this
|
||||
|
@ -739,22 +732,10 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
// Create a parameter environment that represents the implementation's
|
||||
// method.
|
||||
let impl_c_node_id = tcx.hir.as_local_node_id(impl_c.def_id).unwrap();
|
||||
let impl_param_env = tcx.parameter_environment(impl_c.def_id);
|
||||
|
||||
// Create mapping from impl to skolemized.
|
||||
let impl_to_skol_substs = &impl_param_env.free_substs;
|
||||
|
||||
// Create mapping from trait to skolemized.
|
||||
let trait_to_skol_substs = impl_to_skol_substs.rebase_onto(tcx,
|
||||
impl_c.container.id(),
|
||||
trait_to_impl_substs.subst(tcx,
|
||||
impl_to_skol_substs));
|
||||
debug!("compare_const_impl: trait_to_skol_substs={:?}",
|
||||
trait_to_skol_substs);
|
||||
|
||||
// Compute skolemized form of impl and trait const tys.
|
||||
let impl_ty = tcx.type_of(impl_c.def_id).subst(tcx, impl_to_skol_substs);
|
||||
let trait_ty = tcx.type_of(trait_c.def_id).subst(tcx, trait_to_skol_substs);
|
||||
let impl_ty = tcx.type_of(impl_c.def_id);
|
||||
let trait_ty = tcx.type_of(trait_c.def_id).subst(tcx, trait_to_impl_substs);
|
||||
let mut cause = ObligationCause::misc(impl_c_span, impl_c_node_id);
|
||||
|
||||
// There is no "body" here, so just pass dummy id.
|
||||
|
|
|
@ -85,7 +85,6 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
|
|||
let mut fulfillment_cx = traits::FulfillmentContext::new();
|
||||
|
||||
let named_type = tcx.type_of(self_type_did);
|
||||
let named_type = named_type.subst(tcx, &infcx.parameter_environment.free_substs);
|
||||
|
||||
let drop_impl_span = tcx.def_span(drop_impl_did);
|
||||
let fresh_impl_substs =
|
||||
|
|
|
@ -817,8 +817,6 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
check_abi(tcx, span, fn_sig.abi());
|
||||
|
||||
// Compute the fty from point of view of inside fn.
|
||||
let fn_sig =
|
||||
fn_sig.subst(inh.tcx, &inh.parameter_environment.free_substs);
|
||||
let fn_sig =
|
||||
inh.liberate_late_bound_regions(def_id, &fn_sig);
|
||||
let fn_sig =
|
||||
|
@ -1555,10 +1553,6 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
|
||||
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
|
||||
|
||||
fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
|
||||
Some(&self.parameter_environment.free_substs)
|
||||
}
|
||||
|
||||
fn get_type_parameter_bounds(&self, _: Span, def_id: DefId)
|
||||
-> ty::GenericPredicates<'tcx>
|
||||
{
|
||||
|
|
|
@ -397,9 +397,11 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
|||
for implication in implied_bounds {
|
||||
debug!("implication: {:?}", implication);
|
||||
match implication {
|
||||
ImpliedBound::RegionSubRegion(&ty::ReFree(free_a),
|
||||
ImpliedBound::RegionSubRegion(r_a @ &ty::ReEarlyBound(_),
|
||||
&ty::ReVar(vid_b)) |
|
||||
ImpliedBound::RegionSubRegion(r_a @ &ty::ReFree(_),
|
||||
&ty::ReVar(vid_b)) => {
|
||||
self.add_given(free_a, vid_b);
|
||||
self.add_given(r_a, vid_b);
|
||||
}
|
||||
ImpliedBound::RegionSubParam(r_a, param_b) => {
|
||||
self.region_bound_pairs.push((r_a, GenericKind::Param(param_b)));
|
||||
|
@ -1664,7 +1666,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
let mut regions = ty.regions();
|
||||
regions.retain(|r| !r.is_bound()); // ignore late-bound regions
|
||||
regions.retain(|r| !r.is_late_bound()); // ignore late-bound regions
|
||||
bounds.push(VerifyBound::AllRegions(regions));
|
||||
|
||||
// remove bounds that must hold, since they are not interesting
|
||||
|
|
|
@ -159,8 +159,6 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
|||
sig_if_method: Option<&hir::MethodSig>) {
|
||||
let code = self.code.clone();
|
||||
self.for_id(item_id, span).with_fcx(|fcx, this| {
|
||||
let free_substs = &fcx.parameter_environment.free_substs;
|
||||
|
||||
let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id));
|
||||
|
||||
let (mut implied_bounds, self_ty) = match item.container {
|
||||
|
@ -172,14 +170,16 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
|||
match item.kind {
|
||||
ty::AssociatedKind::Const => {
|
||||
let ty = fcx.tcx.type_of(item.def_id);
|
||||
let ty = fcx.instantiate_type_scheme(span, free_substs, &ty);
|
||||
let ty = fcx.normalize_associated_types_in(span, &ty);
|
||||
fcx.register_wf_obligation(ty, span, code.clone());
|
||||
}
|
||||
ty::AssociatedKind::Method => {
|
||||
reject_shadowing_type_parameters(fcx.tcx, item.def_id);
|
||||
let method_ty = fcx.tcx.type_of(item.def_id);
|
||||
let method_ty = fcx.instantiate_type_scheme(span, free_substs, &method_ty);
|
||||
let predicates = fcx.instantiate_bounds(span, item.def_id, free_substs);
|
||||
let method_ty = fcx.normalize_associated_types_in(span, &method_ty);
|
||||
let predicates = fcx.tcx.predicates_of(item.def_id)
|
||||
.instantiate_identity(fcx.tcx);
|
||||
let predicates = fcx.normalize_associated_types_in(span, &predicates);
|
||||
let sig = method_ty.fn_sig();
|
||||
this.check_fn_or_method(fcx, span, sig, &predicates,
|
||||
item.def_id, &mut implied_bounds);
|
||||
|
@ -189,7 +189,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
|||
ty::AssociatedKind::Type => {
|
||||
if item.defaultness.has_value() {
|
||||
let ty = fcx.tcx.type_of(item.def_id);
|
||||
let ty = fcx.instantiate_type_scheme(span, free_substs, &ty);
|
||||
let ty = fcx.normalize_associated_types_in(span, &ty);
|
||||
fcx.register_wf_obligation(ty, span, code.clone());
|
||||
}
|
||||
}
|
||||
|
@ -239,9 +239,9 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let free_substs = &fcx.parameter_environment.free_substs;
|
||||
let def_id = fcx.tcx.hir.local_def_id(item.id);
|
||||
let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
|
||||
let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx);
|
||||
let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
|
||||
this.check_where_clauses(fcx, item.span, &predicates);
|
||||
|
||||
vec![] // no implied bounds in a struct def'n
|
||||
|
@ -317,8 +317,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
|||
}
|
||||
|
||||
self.for_item(item).with_fcx(|fcx, this| {
|
||||
let free_substs = &fcx.parameter_environment.free_substs;
|
||||
let predicates = fcx.instantiate_bounds(item.span, trait_def_id, free_substs);
|
||||
let predicates = fcx.tcx.predicates_of(trait_def_id).instantiate_identity(fcx.tcx);
|
||||
let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
|
||||
this.check_where_clauses(fcx, item.span, &predicates);
|
||||
vec![]
|
||||
});
|
||||
|
@ -326,13 +326,13 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
|||
|
||||
fn check_item_fn(&mut self, item: &hir::Item) {
|
||||
self.for_item(item).with_fcx(|fcx, this| {
|
||||
let free_substs = &fcx.parameter_environment.free_substs;
|
||||
let def_id = fcx.tcx.hir.local_def_id(item.id);
|
||||
let ty = fcx.tcx.type_of(def_id);
|
||||
let item_ty = fcx.instantiate_type_scheme(item.span, free_substs, &ty);
|
||||
let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
|
||||
let sig = item_ty.fn_sig();
|
||||
|
||||
let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
|
||||
let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx);
|
||||
let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
|
||||
|
||||
let mut implied_bounds = vec![];
|
||||
this.check_fn_or_method(fcx, item.span, sig, &predicates,
|
||||
|
@ -348,10 +348,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
|||
|
||||
self.for_item(item).with_fcx(|fcx, this| {
|
||||
let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id));
|
||||
let item_ty = fcx.instantiate_type_scheme(item.span,
|
||||
&fcx.parameter_environment
|
||||
.free_substs,
|
||||
&ty);
|
||||
let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
|
||||
|
||||
fcx.register_wf_obligation(item_ty, item.span, this.code.clone());
|
||||
|
||||
|
@ -367,15 +364,14 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
|||
debug!("check_impl: {:?}", item);
|
||||
|
||||
self.for_item(item).with_fcx(|fcx, this| {
|
||||
let free_substs = &fcx.parameter_environment.free_substs;
|
||||
let item_def_id = fcx.tcx.hir.local_def_id(item.id);
|
||||
|
||||
match *ast_trait_ref {
|
||||
Some(ref ast_trait_ref) => {
|
||||
let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
|
||||
let trait_ref =
|
||||
fcx.instantiate_type_scheme(
|
||||
ast_trait_ref.path.span, free_substs, &trait_ref);
|
||||
fcx.normalize_associated_types_in(
|
||||
ast_trait_ref.path.span, &trait_ref);
|
||||
let obligations =
|
||||
ty::wf::trait_obligations(fcx,
|
||||
fcx.body_id,
|
||||
|
@ -387,12 +383,13 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
|||
}
|
||||
None => {
|
||||
let self_ty = fcx.tcx.type_of(item_def_id);
|
||||
let self_ty = fcx.instantiate_type_scheme(item.span, free_substs, &self_ty);
|
||||
let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty);
|
||||
fcx.register_wf_obligation(self_ty, ast_self_ty.span, this.code.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let predicates = fcx.instantiate_bounds(item.span, item_def_id, free_substs);
|
||||
let predicates = fcx.tcx.predicates_of(item_def_id).instantiate_identity(fcx.tcx);
|
||||
let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
|
||||
this.check_where_clauses(fcx, item.span, &predicates);
|
||||
|
||||
fcx.impl_implied_bounds(item_def_id, item.span)
|
||||
|
@ -425,8 +422,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
|||
def_id: DefId,
|
||||
implied_bounds: &mut Vec<Ty<'tcx>>)
|
||||
{
|
||||
let free_substs = &fcx.parameter_environment.free_substs;
|
||||
let sig = fcx.instantiate_type_scheme(span, free_substs, &sig);
|
||||
let sig = fcx.normalize_associated_types_in(span, &sig);
|
||||
let sig = fcx.liberate_late_bound_regions(def_id, &sig);
|
||||
|
||||
for input_ty in sig.inputs() {
|
||||
|
@ -459,9 +455,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
|||
|
||||
let span = method_sig.decl.inputs[0].span;
|
||||
|
||||
let free_substs = &fcx.parameter_environment.free_substs;
|
||||
let method_ty = fcx.tcx.type_of(method.def_id);
|
||||
let fty = fcx.instantiate_type_scheme(span, free_substs, &method_ty);
|
||||
let fty = fcx.normalize_associated_types_in(span, &method_ty);
|
||||
let sig = fcx.liberate_late_bound_regions(method.def_id, &fty.fn_sig());
|
||||
|
||||
debug!("check_method_receiver: sig={:?}", sig);
|
||||
|
@ -477,7 +472,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
|||
}
|
||||
ExplicitSelf::ByBox => fcx.tcx.mk_box(self_ty)
|
||||
};
|
||||
let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty);
|
||||
let rcvr_ty = fcx.normalize_associated_types_in(span, &rcvr_ty);
|
||||
let rcvr_ty = fcx.liberate_late_bound_regions(method.def_id,
|
||||
&ty::Binder(rcvr_ty));
|
||||
|
||||
|
@ -624,10 +619,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
struct_def.fields().iter()
|
||||
.map(|field| {
|
||||
let field_ty = self.tcx.type_of(self.tcx.hir.local_def_id(field.id));
|
||||
let field_ty = self.instantiate_type_scheme(field.span,
|
||||
&self.parameter_environment
|
||||
.free_substs,
|
||||
&field_ty);
|
||||
let field_ty = self.normalize_associated_types_in(field.span,
|
||||
&field_ty);
|
||||
AdtField { ty: field_ty, span: field.span }
|
||||
})
|
||||
.collect();
|
||||
|
@ -641,19 +634,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<Ty<'tcx>> {
|
||||
let free_substs = &self.parameter_environment.free_substs;
|
||||
match self.tcx.impl_trait_ref(impl_def_id) {
|
||||
Some(ref trait_ref) => {
|
||||
// Trait impl: take implied bounds from all types that
|
||||
// appear in the trait reference.
|
||||
let trait_ref = self.instantiate_type_scheme(span, free_substs, trait_ref);
|
||||
let trait_ref = self.normalize_associated_types_in(span, trait_ref);
|
||||
trait_ref.substs.types().collect()
|
||||
}
|
||||
|
||||
None => {
|
||||
// Inherent impl: take implied bounds from the self type.
|
||||
let self_ty = self.tcx.type_of(impl_def_id);
|
||||
let self_ty = self.instantiate_type_scheme(span, free_substs, &self_ty);
|
||||
let self_ty = self.normalize_associated_types_in(span, &self_ty);
|
||||
vec![self_ty]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ use rustc::infer::{InferCtxt};
|
|||
use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee};
|
||||
use rustc::ty::adjustment;
|
||||
use rustc::ty::fold::{TypeFolder,TypeFoldable};
|
||||
use rustc::util::nodemap::{DefIdMap, DefIdSet};
|
||||
use rustc::util::nodemap::DefIdSet;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
use std::mem;
|
||||
|
@ -71,55 +71,17 @@ struct WritebackCx<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
|
|||
|
||||
tables: ty::TypeckTables<'gcx>,
|
||||
|
||||
// Mapping from free regions of the function to the
|
||||
// early-bound versions of them, visible from the
|
||||
// outside of the function. This is needed by, and
|
||||
// only populated if there are any `impl Trait`.
|
||||
free_to_bound_regions: DefIdMap<ty::Region<'gcx>>,
|
||||
|
||||
body: &'gcx hir::Body,
|
||||
}
|
||||
|
||||
impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, body: &'gcx hir::Body)
|
||||
-> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
let mut wbcx = WritebackCx {
|
||||
WritebackCx {
|
||||
fcx: fcx,
|
||||
tables: ty::TypeckTables::empty(),
|
||||
free_to_bound_regions: DefIdMap(),
|
||||
body: body
|
||||
};
|
||||
|
||||
// Only build the reverse mapping if `impl Trait` is used.
|
||||
if fcx.anon_types.borrow().is_empty() {
|
||||
return wbcx;
|
||||
}
|
||||
|
||||
let gcx = fcx.tcx.global_tcx();
|
||||
let free_substs = fcx.parameter_environment.free_substs;
|
||||
for (i, k) in free_substs.iter().enumerate() {
|
||||
let r = if let Some(r) = k.as_region() {
|
||||
r
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
match *r {
|
||||
ty::ReFree(ty::FreeRegion {
|
||||
bound_region: ty::BoundRegion::BrNamed(def_id, name), ..
|
||||
}) => {
|
||||
let bound_region = gcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
|
||||
index: i as u32,
|
||||
name: name,
|
||||
}));
|
||||
wbcx.free_to_bound_regions.insert(def_id, bound_region);
|
||||
}
|
||||
_ => {
|
||||
bug!("{:?} is not a free region for an early-bound lifetime", r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wbcx
|
||||
}
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
@ -285,22 +247,16 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
|||
let inside_ty = self.resolve(&concrete_ty, &node_id);
|
||||
|
||||
// Convert the type from the function into a type valid outside
|
||||
// the function, by replacing free regions with early-bound ones.
|
||||
// the function, by replacing invalid regions with 'static,
|
||||
// after producing an error for each of them.
|
||||
let outside_ty = gcx.fold_regions(&inside_ty, &mut false, |r, _| {
|
||||
match *r {
|
||||
// 'static is valid everywhere.
|
||||
ty::ReStatic => gcx.types.re_static,
|
||||
ty::ReEmpty => gcx.types.re_empty,
|
||||
|
||||
// Free regions that come from early-bound regions are valid.
|
||||
ty::ReFree(ty::FreeRegion {
|
||||
bound_region: ty::BoundRegion::BrNamed(def_id, ..), ..
|
||||
}) if self.free_to_bound_regions.contains_key(&def_id) => {
|
||||
self.free_to_bound_regions[&def_id]
|
||||
}
|
||||
// 'static and early-bound regions are valid.
|
||||
ty::ReStatic |
|
||||
ty::ReEarlyBound(_) |
|
||||
ty::ReEmpty => r,
|
||||
|
||||
ty::ReFree(_) |
|
||||
ty::ReEarlyBound(_) |
|
||||
ty::ReLateBound(..) |
|
||||
ty::ReScope(_) |
|
||||
ty::ReSkolemized(..) => {
|
||||
|
|
|
@ -19,7 +19,6 @@ use rustc::traits::{self, ObligationCause, Reveal};
|
|||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::TypeFoldable;
|
||||
use rustc::ty::adjustment::CoerceUnsizedInfo;
|
||||
use rustc::ty::subst::Subst;
|
||||
use rustc::ty::util::CopyImplementationError;
|
||||
use rustc::infer;
|
||||
|
||||
|
@ -107,7 +106,6 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|
||||
let span = tcx.hir.span(impl_node_id);
|
||||
let param_env = tcx.parameter_environment(impl_did);
|
||||
let self_type = self_type.subst(tcx, ¶m_env.free_substs);
|
||||
assert!(!self_type.has_escaping_regions());
|
||||
|
||||
debug!("visit_implementation_of_copy: self_type={:?} (free)",
|
||||
|
@ -202,8 +200,6 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|
||||
let span = tcx.hir.span(impl_node_id);
|
||||
let param_env = tcx.parameter_environment(impl_did);
|
||||
let source = source.subst(tcx, ¶m_env.free_substs);
|
||||
let target = target.subst(tcx, ¶m_env.free_substs);
|
||||
assert!(!source.has_escaping_regions());
|
||||
|
||||
let err_info = CoerceUnsizedInfo { custom_kind: None };
|
||||
|
|
|
@ -205,10 +205,6 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
|
|||
self.tcx.at(span).type_param_predicates((self.item_def_id, def_id))
|
||||
}
|
||||
|
||||
fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn re_infer(&self, _span: Span, _def: Option<&ty::RegionParameterDef>)
|
||||
-> Option<ty::Region<'tcx>> {
|
||||
None
|
||||
|
@ -1299,6 +1295,7 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let mut index = parent_count + has_own_self as u32;
|
||||
for param in early_bound_lifetimes_from_generics(tcx, ast_generics) {
|
||||
let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
|
||||
def_id: tcx.hir.local_def_id(param.lifetime.id),
|
||||
index: index,
|
||||
name: param.lifetime.name
|
||||
}));
|
||||
|
|
|
@ -11,17 +11,18 @@
|
|||
pub trait Resources<'a> {}
|
||||
|
||||
pub trait Buffer<'a, R: Resources<'a>> {
|
||||
//~^ NOTE the lifetime 'a as defined on the trait at 13:0...
|
||||
//~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the trait
|
||||
|
||||
fn select(&self) -> BufferViewHandle<R>;
|
||||
//~^ ERROR mismatched types
|
||||
//~| lifetime mismatch
|
||||
//~| NOTE expected type `Resources<'_>`
|
||||
//~| NOTE the lifetime 'a as defined on the method body at 14:4...
|
||||
//~| NOTE ...does not necessarily outlive the anonymous lifetime #1 defined on the method body
|
||||
//~| ERROR mismatched types
|
||||
//~| lifetime mismatch
|
||||
//~| NOTE expected type `Resources<'_>`
|
||||
//~| NOTE the anonymous lifetime #1 defined on the method body at 14:4...
|
||||
//~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the method body
|
||||
//~| NOTE the anonymous lifetime #1 defined on the method body at 17:4...
|
||||
}
|
||||
|
||||
pub struct BufferViewHandle<'a, R: 'a+Resources<'a>>(&'a R);
|
||||
|
|
|
@ -11,13 +11,14 @@
|
|||
struct RepeatMut<'a, T>(T, &'a ());
|
||||
|
||||
impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
|
||||
//~^ NOTE ...does not necessarily outlive the lifetime 'a as defined on the impl
|
||||
|
||||
type Item = &'a mut T;
|
||||
fn next(&'a mut self) -> Option<Self::Item>
|
||||
//~^ ERROR method not compatible with trait
|
||||
//~| lifetime mismatch
|
||||
//~| NOTE expected type `fn(&mut RepeatMut<'a, T>) -> std::option::Option<&mut T>`
|
||||
//~| NOTE the anonymous lifetime #1 defined on the method body
|
||||
//~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the method body
|
||||
{
|
||||
Some(&mut self.0)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue