rustc: use DefId instead of CodeExtent for FreeRegion's scope.

This commit is contained in:
Eduard-Mihai Burtescu 2017-05-07 19:57:51 +03:00
parent 72aab7ade4
commit 6d4c2141b5
32 changed files with 149 additions and 234 deletions

View File

@ -409,11 +409,6 @@ impl_stable_hash_for!(enum ::middle::resolve_lifetime::Region {
Free(call_site_scope_data, decl)
});
impl_stable_hash_for!(struct ::middle::region::CallSiteScopeData {
fn_id,
body_id
});
impl_stable_hash_for!(struct ty::DebruijnIndex {
depth
});
@ -466,7 +461,7 @@ impl_stable_hash_for!(struct ty::adjustment::CoerceUnsizedInfo {
custom_kind
});
impl_stable_hash_for!(struct ty::FreeRegion<'tcx> {
impl_stable_hash_for!(struct ty::FreeRegion {
scope,
bound_region
});

View File

@ -184,7 +184,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
};
let node = fr.scope.map(|s| s.node_id())
let node = self.hir.as_local_node_id(fr.scope)
.unwrap_or(DUMMY_NODE_ID);
let unknown;
let tag = match self.hir.find(node) {

View File

@ -1009,7 +1009,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
pub fn add_given(&self,
sub: ty::FreeRegion<'tcx>,
sub: ty::FreeRegion,
sup: ty::RegionVid)
{
self.region_vars.add_given(sub, sup);

View File

@ -127,7 +127,7 @@ pub enum UndoLogEntry<'tcx> {
AddVerify(usize),
/// We added the given `given`
AddGiven(ty::FreeRegion<'tcx>, ty::RegionVid),
AddGiven(ty::FreeRegion, ty::RegionVid),
/// We added a GLB/LUB "combinaton variable"
AddCombination(CombineMapType, TwoRegions<'tcx>),
@ -213,7 +213,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<'tcx>, ty::RegionVid)>>,
givens: RefCell<FxHashSet<(ty::FreeRegion, ty::RegionVid)>>,
lubs: RefCell<CombineMap<'tcx>>,
glbs: RefCell<CombineMap<'tcx>>,
@ -661,7 +661,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
}
}
pub fn add_given(&self, sub: ty::FreeRegion<'tcx>, sup: ty::RegionVid) {
pub fn add_given(&self, sub: ty::FreeRegion, sup: ty::RegionVid) {
// cannot add givens once regions are resolved
assert!(self.values_are_none());
@ -931,19 +931,18 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
b);
}
(&ReFree(fr), &ReScope(s_id)) |
(&ReScope(s_id), &ReFree(fr)) => {
(&ReFree(ref fr), &ReScope(s_id)) |
(&ReScope(s_id), &ReFree(ref fr)) => {
// A "free" region can be interpreted as "some region
// at least as big as the block fr.scope_id". So, we can
// at least as big as fr.scope". So, we can
// reasonably compare free regions and scopes:
if let Some(fr_scope) = fr.scope {
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_id` is bigger than
// the scope region `s_id`, then the LUB is the free
// region itself:
return self.tcx.mk_region(ReFree(fr));
}
let fr_scope = region_rels.region_maps.free_extent(self.tcx, fr);
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));
}
// otherwise, we don't know what the free region is,

View File

@ -71,12 +71,9 @@ 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(fr)) => {
// 1. It is safe to unwrap `fr.scope` because we
// should only ever wind up comparing against
// `ReScope` in the context of a method or
// body, where `fr.scope` should be `Some`.
self.region_maps.is_subscope_of(sub_scope, fr.scope.unwrap() /*1*/) ||
(&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)
}

View File

@ -1440,9 +1440,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// within the fn body, late-bound regions are liberated
// and must outlive the *call-site* of the function.
let fn_ret =
self.ir.tcx.liberate_late_bound_regions(
Some(self.ir.tcx.call_site_extent(id)),
&fn_ret);
self.ir.tcx.liberate_late_bound_regions(def_id, &fn_ret);
if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() {
let param_env = self.ir.tcx.parameter_environment(def_id);

View File

@ -790,7 +790,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
// The environment of a closure is guaranteed to
// outlive any bindings introduced in the body of the
// closure itself.
scope: Some(self.tcx().call_site_extent(upvar_id.closure_expr_id)),
scope: self.tcx().hir.local_def_id(upvar_id.closure_expr_id),
bound_region: ty::BrEnv
}));

View File

@ -120,23 +120,6 @@ pub enum CodeExtentData {
Remainder(BlockRemainder)
}
/// extent of call-site for a function/method.
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable,
RustcDecodable, Debug, Copy)]
pub struct CallSiteScopeData {
pub fn_id: ast::NodeId, pub body_id: ast::NodeId,
}
impl CallSiteScopeData {
pub fn to_code_extent<'a, 'tcx, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> CodeExtent<'tcx> {
tcx.intern_code_extent(
match *self {
CallSiteScopeData { fn_id, body_id } =>
CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id },
})
}
}
/// Represents a subscope of `block` for a binding that is introduced
/// by `block.stmts[first_statement_index]`. Such subscopes represent
/// a suffix of the block. Note that each subscope does not include
@ -612,6 +595,14 @@ impl<'tcx> RegionMaps<'tcx> {
}
}
}
/// 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)
-> CodeExtent<'tcx> {
let scope_id = tcx.hir.as_local_node_id(fr.scope).unwrap();
tcx.call_site_extent(scope_id)
}
}
/// Records the lifetime of a local variable as `cx.var_parent`

View File

@ -19,7 +19,6 @@ use hir::map::Map;
use session::Session;
use hir::def::Def;
use hir::def_id::DefId;
use middle::region;
use ty;
use std::cell::Cell;
@ -42,7 +41,7 @@ pub enum Region {
EarlyBound(/* index */ u32, /* lifetime decl */ ast::NodeId),
LateBound(ty::DebruijnIndex, /* lifetime decl */ ast::NodeId),
LateBoundAnon(ty::DebruijnIndex, /* anon index */ u32),
Free(region::CallSiteScopeData, /* lifetime decl */ ast::NodeId),
Free(DefId, /* lifetime decl */ ast::NodeId),
}
impl Region {
@ -897,9 +896,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
if let Some(mut def) = result {
if let Some(body_id) = outermost_body {
let fn_id = self.hir_map.body_owner(body_id);
let scope_data = region::CallSiteScopeData {
fn_id: fn_id, body_id: body_id.node_id
};
match self.hir_map.get(fn_id) {
hir::map::NodeItem(&hir::Item {
node: hir::ItemFn(..), ..
@ -910,7 +906,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
hir::map::NodeImplItem(&hir::ImplItem {
node: hir::ImplItemKind::Method(..), ..
}) => {
def = Region::Free(scope_data, def.id().unwrap());
let scope = self.hir_map.local_def_id(fn_id);
def = Region::Free(scope, def.id().unwrap());
}
_ => {}
}

View File

@ -206,7 +206,7 @@ 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, None);
let free_substs = self.construct_free_substs(def_id);
let predicates = self.predicates_of(def_id);
let predicates = predicates.instantiate(self, free_substs).predicates;
elaborate_predicates(self, predicates)

View File

@ -655,11 +655,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.intern_code_extent(CodeExtentData::Misc(n))
}
// Returns the code extent for an item - the destruction scope.
pub fn item_extent(self, n: ast::NodeId) -> CodeExtent<'gcx> {
self.intern_code_extent(CodeExtentData::DestructionScope(n))
}
pub fn call_site_extent(self, fn_id: ast::NodeId) -> CodeExtent<'gcx> {
self.intern_code_extent(CodeExtentData::CallSiteScope {
fn_id,
@ -852,15 +847,6 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::FreeRegion<'a> {
type Lifted = ty::FreeRegion<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
let scope = self.scope.map(|code_extent| tcx.intern_code_extent(*code_extent));
let bound_region = self.bound_region;
Some(ty::FreeRegion { scope, bound_region })
}
}
impl<'a, 'tcx> Lift<'tcx> for Region<'a> {
type Lifted = Region<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Region<'tcx>> {

View File

@ -39,7 +39,7 @@
//! These methods return true to indicate that the visitor has found what it is looking for
//! and does not need to visit anything else.
use middle::region;
use hir::def_id::DefId;
use ty::subst::Substs;
use ty::adjustment;
use ty::{self, Binder, Ty, TyCtxt, TypeFlags};
@ -330,7 +330,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// Replace any late-bound regions bound in `value` with free variants attached to scope-id
/// `scope_id`.
pub fn liberate_late_bound_regions<T>(self,
all_outlive_scope: Option<region::CodeExtent<'tcx>>,
all_outlive_scope: DefId,
value: &Binder<T>)
-> T
where T : TypeFoldable<'tcx>

View File

@ -23,7 +23,6 @@ use ich::StableHashingContext;
use middle::const_val::ConstVal;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use middle::privacy::AccessLevels;
use middle::region::CodeExtent;
use middle::resolve_lifetime::ObjectLifetimeDefault;
use mir::Mir;
use traits;
@ -1244,28 +1243,11 @@ pub struct ParameterEnvironment<'tcx> {
/// See `construct_free_substs` for details.
pub free_substs: &'tcx Substs<'tcx>,
/// Each type parameter has an implicit region bound that
/// indicates it must outlive at least the function body (the user
/// may specify stronger requirements). This field indicates the
/// region of the callee. If it is `None`, then the parameter
/// environment is for an item or something where the "callee" is
/// not clear.
pub implicit_region_bound: Option<ty::Region<'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.
pub caller_bounds: &'tcx [ty::Predicate<'tcx>],
/// Scope that is attached to free regions for this scope. This is
/// usually the id of the fn body, but for more abstract scopes
/// like structs we use None or the item extent.
///
/// FIXME(#3696). It would be nice to refactor so that free
/// regions don't have this implicit scope and instead introduce
/// relationships in the environment.
pub free_id_outlive: Option<CodeExtent<'tcx>>,
/// A cache for `moves_by_default`.
pub is_copy_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
@ -1283,9 +1265,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
{
ParameterEnvironment {
free_substs: self.free_substs,
implicit_region_bound: self.implicit_region_bound,
caller_bounds: caller_bounds,
free_id_outlive: self.free_id_outlive,
is_copy_cache: RefCell::new(FxHashMap()),
is_sized_cache: RefCell::new(FxHashMap()),
is_freeze_cache: RefCell::new(FxHashMap()),
@ -2394,8 +2374,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
ty::ParameterEnvironment {
free_substs: self.intern_substs(&[]),
caller_bounds: Slice::empty(),
implicit_region_bound: None,
free_id_outlive: None,
is_copy_cache: RefCell::new(FxHashMap()),
is_sized_cache: RefCell::new(FxHashMap()),
is_freeze_cache: RefCell::new(FxHashMap()),
@ -2407,15 +2385,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// 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,
free_id_outlive: Option<CodeExtent<'gcx>>)
-> &'gcx Substs<'gcx> {
pub fn construct_free_substs(self, def_id: DefId) -> &'gcx Substs<'gcx> {
let substs = Substs::for_item(self.global_tcx(), def_id, |def, _| {
// map bound 'a => free 'a
self.global_tcx().mk_region(ReFree(FreeRegion {
scope: free_id_outlive,
scope: def_id,
bound_region: def.to_bound_region()
}))
}, |def, _| {
@ -2433,14 +2408,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
// Construct the free substs.
//
let free_id_outlive = self.hir.as_local_node_id(def_id).map(|id| {
if self.hir.maybe_body_owned_by(id).is_some() {
self.call_site_extent(id)
} else {
self.item_extent(id)
}
});
let free_substs = self.construct_free_substs(def_id, free_id_outlive);
let free_substs = self.construct_free_substs(def_id);
//
// Compute the bounds on Self and the type parameters.
@ -2449,7 +2417,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
let tcx = self.global_tcx();
let generic_predicates = tcx.predicates_of(def_id);
let bounds = generic_predicates.instantiate(tcx, free_substs);
let bounds = tcx.liberate_late_bound_regions(free_id_outlive, &ty::Binder(bounds));
let bounds = tcx.liberate_late_bound_regions(def_id, &ty::Binder(bounds));
let predicates = bounds.predicates;
// Finally, we have to normalize the bounds in the environment, in
@ -2466,17 +2434,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
//
let unnormalized_env = ty::ParameterEnvironment {
free_substs: free_substs,
implicit_region_bound: free_id_outlive.map(|f| tcx.mk_region(ty::ReScope(f))),
free_substs,
caller_bounds: tcx.intern_predicates(&predicates),
free_id_outlive: free_id_outlive,
is_copy_cache: RefCell::new(FxHashMap()),
is_sized_cache: RefCell::new(FxHashMap()),
is_freeze_cache: RefCell::new(FxHashMap()),
};
let body_id = free_id_outlive.map(|f| f.node_id())
.unwrap_or(DUMMY_NODE_ID);
let body_id = self.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| {
self.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id)
});
let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
}

View File

@ -43,12 +43,8 @@ pub struct TypeAndMut<'tcx> {
RustcEncodable, RustcDecodable, Copy)]
/// A "free" region `fr` can be interpreted as "some region
/// at least as big as the scope `fr.scope`".
///
/// If `fr.scope` is None, then this is in some context (e.g., an
/// impl) where lifetimes are more abstract and the notion of the
/// caller/callee stack frames are not applicable.
pub struct FreeRegion<'tcx> {
pub scope: Option<region::CodeExtent<'tcx>>,
pub struct FreeRegion {
pub scope: DefId,
pub bound_region: BoundRegion,
}
@ -760,7 +756,7 @@ pub enum RegionKind<'tcx> {
/// When checking a function body, the types of all arguments and so forth
/// that refer to bound region parameters are modified to refer to free
/// region parameters.
ReFree(FreeRegion<'tcx>),
ReFree(FreeRegion),
/// A concrete region naming some statically determined extent
/// (e.g. an expression or sequence of statements) within the

View File

@ -508,10 +508,8 @@ impl<'tcx> fmt::Debug for ty::ParameterEnvironment<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ParameterEnvironment(\
free_substs={:?}, \
implicit_region_bound={:?}, \
caller_bounds={:?})",
self.free_substs,
self.implicit_region_bound,
self.caller_bounds)
}
}
@ -544,7 +542,7 @@ impl<'tcx> fmt::Display for ty::RegionKind<'tcx> {
}
}
impl<'tcx> fmt::Debug for ty::FreeRegion<'tcx> {
impl fmt::Debug for ty::FreeRegion {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ReFree({:?}, {:?})",
self.scope, self.bound_region)

View File

@ -353,7 +353,9 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
let loan_scope = match *loan_region {
ty::ReScope(scope) => scope,
ty::ReFree(ref fr) => fr.scope.unwrap_or(self.item_ub),
ty::ReFree(ref fr) => {
self.bccx.region_maps.free_extent(self.tcx(), fr)
}
ty::ReStatic => self.item_ub,

View File

@ -330,15 +330,15 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize)
}
pub fn re_free(&self, nid: ast::NodeId, id: u32) -> ty::Region<'tcx> {
pub fn re_free(&self, id: u32) -> ty::Region<'tcx> {
self.infcx.tcx.mk_region(ty::ReFree(ty::FreeRegion {
scope: Some(self.tcx().node_extent(nid)),
scope: self.infcx.tcx.hir.local_def_id(ast::CRATE_NODE_ID),
bound_region: ty::BrAnon(id),
}))
}
pub fn t_rptr_free(&self, nid: u32, id: u32) -> Ty<'tcx> {
let r = self.re_free(ast::NodeId::from_u32(nid), id);
pub fn t_rptr_free(&self, id: u32) -> Ty<'tcx> {
let r = self.re_free(id);
self.infcx.tcx.mk_imm_ref(r, self.tcx().types.isize)
}
@ -464,7 +464,7 @@ fn sub_free_bound_false() {
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
let t_rptr_free1 = env.t_rptr_free(1, 1);
let t_rptr_free1 = env.t_rptr_free(1);
let t_rptr_bound1 = env.t_rptr_late_bound(1);
env.check_not_sub(env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
env.t_fn(&[t_rptr_bound1], env.tcx().types.isize));
@ -482,7 +482,7 @@ fn sub_bound_free_true() {
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
let t_rptr_bound1 = env.t_rptr_late_bound(1);
let t_rptr_free1 = env.t_rptr_free(1, 1);
let t_rptr_free1 = env.t_rptr_free(1);
env.check_sub(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free1], env.tcx().types.isize));
})
@ -518,7 +518,7 @@ fn lub_free_bound_infer() {
env.create_simple_region_hierarchy();
let t_infer1 = env.infcx.next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP));
let t_rptr_bound1 = env.t_rptr_late_bound(1);
let t_rptr_free1 = env.t_rptr_free(1, 1);
let t_rptr_free1 = env.t_rptr_free(1);
env.check_lub(env.t_fn(&[t_infer1], env.tcx().types.isize),
env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free1], env.tcx().types.isize));
@ -541,7 +541,7 @@ fn lub_bound_free() {
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
let t_rptr_bound1 = env.t_rptr_late_bound(1);
let t_rptr_free1 = env.t_rptr_free(1, 1);
let t_rptr_free1 = env.t_rptr_free(1);
env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free1], env.tcx().types.isize));
@ -574,8 +574,8 @@ fn lub_bound_bound_inverse_order() {
fn lub_free_free() {
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
let t_rptr_free1 = env.t_rptr_free(1, 1);
let t_rptr_free2 = env.t_rptr_free(1, 2);
let t_rptr_free1 = env.t_rptr_free(1);
let t_rptr_free2 = env.t_rptr_free(2);
let t_rptr_static = env.t_rptr_static();
env.check_lub(env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free2], env.tcx().types.isize),
@ -600,8 +600,8 @@ fn lub_returning_scope() {
fn glb_free_free_with_common_scope() {
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
let t_rptr_free1 = env.t_rptr_free(1, 1);
let t_rptr_free2 = env.t_rptr_free(1, 2);
let t_rptr_free1 = env.t_rptr_free(1);
let t_rptr_free2 = env.t_rptr_free(2);
let t_rptr_scope = env.t_rptr_scope(1);
env.check_glb(env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free2], env.tcx().types.isize),
@ -625,7 +625,7 @@ fn glb_bound_free() {
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
let t_rptr_bound1 = env.t_rptr_late_bound(1);
let t_rptr_free1 = env.t_rptr_free(1, 1);
let t_rptr_free1 = env.t_rptr_free(1);
env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
env.t_fn(&[t_rptr_bound1], env.tcx().types.isize));
@ -751,7 +751,7 @@ fn escaping() {
assert!(!env.t_nil().has_escaping_regions());
let t_rptr_free1 = env.t_rptr_free(1, 1);
let t_rptr_free1 = env.t_rptr_free(1);
assert!(!t_rptr_free1.has_escaping_regions());
let t_rptr_bound1 = env.t_rptr_late_bound_with_debruijn(1, ty::DebruijnIndex::new(1));

View File

@ -206,13 +206,14 @@ fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-> Ty<'tcx> {
let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_id);
let closure_def_id = tcx.hir.local_def_id(closure_expr_id);
let region = ty::ReFree(ty::FreeRegion {
scope: Some(tcx.call_site_extent(closure_expr_id)),
scope: closure_def_id,
bound_region: ty::BoundRegion::BrEnv,
});
let region = tcx.mk_region(region);
match tcx.closure_kind(tcx.hir.local_def_id(closure_expr_id)) {
match tcx.closure_kind(closure_def_id) {
ty::ClosureKind::Fn =>
tcx.mk_ref(region,
ty::TypeAndMut { ty: closure_ty,

View File

@ -14,7 +14,6 @@ use rustc_const_math::ConstInt;
use hair::cx::Cx;
use hair::cx::block;
use hair::cx::to_ref::ToRef;
use rustc::hir::map;
use rustc::hir::def::{Def, CtorKind};
use rustc::middle::const_val::ConstVal;
use rustc::ty::{self, AdtKind, VariantDef, Ty};
@ -807,33 +806,20 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
closure_expr_id);
let var_ty = cx.tables().node_id_to_type(id_var);
let body_id = match cx.tcx.hir.find(closure_expr_id) {
Some(map::NodeExpr(expr)) => {
match expr.node {
hir::ExprClosure(.., body, _) => body.node_id,
_ => {
span_bug!(expr.span, "closure expr is not a closure expr");
}
}
}
_ => {
span_bug!(expr.span, "ast-map has garbage for closure expr");
}
};
// FIXME free regions in closures are not right
let closure_ty = cx.tables().node_id_to_type(closure_expr_id);
// FIXME we're just hard-coding the idea that the
// signature will be &self or &mut self and hence will
// have a bound region with number 0
let closure_def_id = cx.tcx.hir.local_def_id(closure_expr_id);
let region = ty::ReFree(ty::FreeRegion {
scope: Some(cx.tcx.node_extent(body_id)),
scope: closure_def_id,
bound_region: ty::BoundRegion::BrAnon(0),
});
let region = cx.tcx.mk_region(region);
let self_expr = match cx.tcx.closure_kind(cx.tcx.hir.local_def_id(closure_expr_id)) {
let self_expr = match cx.tcx.closure_kind(closure_def_id) {
ty::ClosureKind::Fn => {
let ref_closure_ty = cx.tcx.mk_ref(region,
ty::TypeAndMut {

View File

@ -129,7 +129,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
Some(&rl::Region::Free(scope, id)) => {
let name = tcx.hir.name(id);
tcx.mk_region(ty::ReFree(ty::FreeRegion {
scope: Some(scope.to_code_extent(tcx)),
scope,
bound_region: ty::BrNamed(tcx.hir.local_def_id(id), name)
}))

View File

@ -73,8 +73,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type);
let extent = self.tcx.call_site_extent(expr.id);
let fn_sig = self.tcx.liberate_late_bound_regions(Some(extent), &sig);
let fn_sig = self.tcx.liberate_late_bound_regions(expr_def_id, &sig);
let fn_sig = self.inh.normalize_associated_types_in(body.value.span,
body.value.id, &fn_sig);

View File

@ -226,7 +226,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
normalize_cause.clone());
tcx.infer_ctxt(trait_param_env, Reveal::UserFacing).enter(|infcx| {
let inh = Inherited::new(infcx);
let inh = Inherited::new(infcx, impl_m.def_id);
let infcx = &inh.infcx;
debug!("compare_impl_method: caller_bounds={:?}",
@ -283,7 +283,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
let trait_sig = tcx.liberate_late_bound_regions(
infcx.parameter_environment.free_id_outlive,
impl_m.def_id,
&m_sig(trait_m));
let trait_sig =
trait_sig.subst(tcx, trait_to_skol_substs);
@ -726,7 +726,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
let inh = Inherited::new(infcx);
let inh = Inherited::new(infcx, impl_c.def_id);
let infcx = &inh.infcx;
// The below is for the most part highly similar to the procedure

View File

@ -176,6 +176,14 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
// variables to get the concrete type, which can be used to
// deanonymize TyAnon, after typeck is done with all functions.
anon_types: RefCell<NodeMap<Ty<'tcx>>>,
/// Each type parameter has an implicit region bound that
/// indicates it must outlive at least the function body (the user
/// may specify stronger requirements). This field indicates the
/// region of the callee. If it is `None`, then the parameter
/// environment is for an item or something where the "callee" is
/// not clear.
implicit_region_bound: Option<ty::Region<'tcx>>,
}
impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> {
@ -522,7 +530,8 @@ impl<'a, 'gcx, 'tcx> Deref for FnCtxt<'a, 'gcx, 'tcx> {
/// Necessary because we can't write the following bound:
/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(Inherited<'b, 'gcx, 'tcx>).
pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
infcx: infer::InferCtxtBuilder<'a, 'gcx, 'tcx>
infcx: infer::InferCtxtBuilder<'a, 'gcx, 'tcx>,
def_id: DefId,
}
impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
@ -531,7 +540,8 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
let tables = ty::TypeckTables::empty();
let param_env = tcx.parameter_environment(def_id);
InheritedBuilder {
infcx: tcx.infer_ctxt((tables, param_env), Reveal::UserFacing)
infcx: tcx.infer_ctxt((tables, param_env), Reveal::UserFacing),
def_id,
}
}
}
@ -540,12 +550,24 @@ impl<'a, 'gcx, 'tcx> InheritedBuilder<'a, 'gcx, 'tcx> {
fn enter<F, R>(&'tcx mut self, f: F) -> R
where F: for<'b> FnOnce(Inherited<'b, 'gcx, 'tcx>) -> R
{
self.infcx.enter(|infcx| f(Inherited::new(infcx)))
let def_id = self.def_id;
self.infcx.enter(|infcx| f(Inherited::new(infcx, def_id)))
}
}
impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self {
fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> Self {
let tcx = infcx.tcx;
let item_id = tcx.hir.as_local_node_id(def_id);
let body_id = item_id.and_then(|id| tcx.hir.maybe_body_owned_by(id));
let implicit_region_bound = item_id.and_then(|id| {
if body_id.is_some() {
Some(tcx.mk_region(ty::ReScope(tcx.call_site_extent(id))))
} else {
None
}
});
Inherited {
infcx: infcx,
fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
@ -553,6 +575,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
deferred_call_resolutions: RefCell::new(DefIdMap()),
deferred_cast_checks: RefCell::new(Vec::new()),
anon_types: RefCell::new(NodeMap()),
implicit_region_bound,
}
}
@ -778,11 +801,10 @@ 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_scope = inh.tcx.call_site_extent(id);
let fn_sig =
fn_sig.subst(inh.tcx, &inh.parameter_environment.free_substs);
let fn_sig =
inh.tcx.liberate_late_bound_regions(Some(fn_scope), &fn_sig);
inh.tcx.liberate_late_bound_regions(def_id, &fn_sig);
let fn_sig =
inh.normalize_associated_types_in(body.value.span, body_id.node_id, &fn_sig);

View File

@ -1612,8 +1612,6 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
}
fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
let param_env = &self.parameter_environment;
debug!("param_bound(param_ty={:?})",
param_ty);
@ -1621,7 +1619,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
// Add in the default bound of fn body that applies to all in
// scope type parameters:
param_bounds.extend(param_env.implicit_region_bound);
param_bounds.extend(self.implicit_region_bound);
VerifyBound::AnyRegion(param_bounds)
}

View File

@ -13,7 +13,6 @@ use check::{Inherited, FnCtxt};
use constrained_type_params::{identify_constrained_type_params, Parameter};
use hir::def_id::DefId;
use middle::region::{CodeExtent};
use rustc::traits::{self, ObligationCauseCode};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::util::nodemap::{FxHashSet, FxHashMap};
@ -161,7 +160,6 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
let code = self.code.clone();
self.for_id(item_id, span).with_fcx(|fcx, this| {
let free_substs = &fcx.parameter_environment.free_substs;
let free_id_outlive = fcx.parameter_environment.free_id_outlive;
let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id));
@ -184,10 +182,9 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
let predicates = fcx.instantiate_bounds(span, item.def_id, free_substs);
let sig = method_ty.fn_sig();
this.check_fn_or_method(fcx, span, sig, &predicates,
free_id_outlive, &mut implied_bounds);
item.def_id, &mut implied_bounds);
let sig_if_method = sig_if_method.expect("bad signature for method");
this.check_method_receiver(fcx, sig_if_method, &item,
free_id_outlive, self_ty);
this.check_method_receiver(fcx, sig_if_method, &item, self_ty);
}
ty::AssociatedKind::Type => {
if item.defaultness.has_value() {
@ -338,9 +335,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
let mut implied_bounds = vec![];
let free_id_outlive = fcx.tcx.call_site_extent(item.id);
this.check_fn_or_method(fcx, item.span, sig, &predicates,
Some(free_id_outlive), &mut implied_bounds);
def_id, &mut implied_bounds);
implied_bounds
})
}
@ -426,12 +422,12 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
span: Span,
sig: ty::PolyFnSig<'tcx>,
predicates: &ty::InstantiatedPredicates<'tcx>,
free_id_outlive: Option<CodeExtent<'tcx>>,
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.tcx.liberate_late_bound_regions(free_id_outlive, &sig);
let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig);
for input_ty in sig.inputs() {
fcx.register_wf_obligation(&input_ty, span, self.code.clone());
@ -450,7 +446,6 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
method_sig: &hir::MethodSig,
method: &ty::AssociatedItem,
free_id_outlive: Option<CodeExtent<'tcx>>,
self_ty: ty::Ty<'tcx>)
{
// check that the type of the method's receiver matches the
@ -467,7 +462,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
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 sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.fn_sig());
let sig = fcx.tcx.liberate_late_bound_regions(method.def_id, &fty.fn_sig());
debug!("check_method_receiver: sig={:?}", sig);
@ -483,7 +478,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.tcx.liberate_late_bound_regions(free_id_outlive,
let rcvr_ty = fcx.tcx.liberate_late_bound_regions(method.def_id,
&ty::Binder(rcvr_ty));
debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);

View File

@ -16,9 +16,9 @@ impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
//~^ 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
{
//~^ NOTE the anonymous lifetime #1 defined on the body
//~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the body
Some(&mut self.0)
}
}

View File

@ -4,19 +4,17 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content...
12 | if x > y { x } else { y }
| ^
|
note: ...the reference is valid for the lifetime 'a as defined on the body at 11:43...
--> $DIR/ex1-return-one-existing-name-if-else.rs:11:44
note: ...the reference is valid for the lifetime 'a as defined on the function body at 11:0...
--> $DIR/ex1-return-one-existing-name-if-else.rs:11:1
|
11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
| ____________________________________________^
11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
12 | | if x > y { x } else { y }
13 | | }
| |_^
note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the body at 11:43
--> $DIR/ex1-return-one-existing-name-if-else.rs:11:44
note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the function body at 11:0
--> $DIR/ex1-return-one-existing-name-if-else.rs:11:1
|
11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
| ____________________________________________^
11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
12 | | if x > y { x } else { y }
13 | | }
| |_^

View File

@ -6,19 +6,17 @@ error[E0308]: mismatched types
|
= note: expected type `Ref<'a, _>`
found type `Ref<'_, _>`
note: the anonymous lifetime #2 defined on the body at 15:51...
--> $DIR/ex2a-push-one-existing-name.rs:15:52
note: the anonymous lifetime #2 defined on the function body at 15:0...
--> $DIR/ex2a-push-one-existing-name.rs:15:1
|
15 | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
| ____________________________________________________^
15 | / fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
note: ...does not necessarily outlive the lifetime 'a as defined on the body at 15:51
--> $DIR/ex2a-push-one-existing-name.rs:15:52
note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 15:0
--> $DIR/ex2a-push-one-existing-name.rs:15:1
|
15 | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
| ____________________________________________________^
15 | / fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^

View File

@ -6,19 +6,17 @@ error[E0308]: mismatched types
|
= note: expected type `Ref<'_, _>`
found type `Ref<'_, _>`
note: the anonymous lifetime #3 defined on the body at 15:43...
--> $DIR/ex2b-push-no-existing-names.rs:15:44
note: the anonymous lifetime #3 defined on the function body at 15:0...
--> $DIR/ex2b-push-no-existing-names.rs:15:1
|
15 | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
| ____________________________________________^
15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 15:43
--> $DIR/ex2b-push-no-existing-names.rs:15:44
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 15:0
--> $DIR/ex2b-push-no-existing-names.rs:15:1
|
15 | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
| ____________________________________________^
15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^

View File

@ -4,11 +4,10 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d
16 | let z = Ref { data: y.data };
| ^^^
|
note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66...
--> $DIR/ex2c-push-inference-variable.rs:15:67
note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
--> $DIR/ex2c-push-inference-variable.rs:15:1
|
15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
| ___________________________________________________________________^
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let z = Ref { data: y.data };
17 | | x.push(z);
18 | | }
@ -18,11 +17,10 @@ note: ...so that reference does not outlive borrowed content
|
16 | let z = Ref { data: y.data };
| ^^^^^^
note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66...
--> $DIR/ex2c-push-inference-variable.rs:15:67
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
--> $DIR/ex2c-push-inference-variable.rs:15:1
|
15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
| ___________________________________________________________________^
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let z = Ref { data: y.data };
17 | | x.push(z);
18 | | }

View File

@ -4,11 +4,10 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d
17 | let b = Ref { data: y.data };
| ^^^
|
note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66...
--> $DIR/ex2d-push-inference-variable-2.rs:15:67
note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
--> $DIR/ex2d-push-inference-variable-2.rs:15:1
|
15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
| ___________________________________________________________________^
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let a: &mut Vec<Ref<i32>> = x;
17 | | let b = Ref { data: y.data };
18 | | a.push(b);
@ -19,11 +18,10 @@ note: ...so that reference does not outlive borrowed content
|
17 | let b = Ref { data: y.data };
| ^^^^^^
note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66...
--> $DIR/ex2d-push-inference-variable-2.rs:15:67
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
--> $DIR/ex2d-push-inference-variable-2.rs:15:1
|
15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
| ___________________________________________________________________^
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let a: &mut Vec<Ref<i32>> = x;
17 | | let b = Ref { data: y.data };
18 | | a.push(b);

View File

@ -4,11 +4,10 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d
17 | let b = Ref { data: y.data };
| ^^^
|
note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66...
--> $DIR/ex2e-push-inference-variable-3.rs:15:67
note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
--> $DIR/ex2e-push-inference-variable-3.rs:15:1
|
15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
| ___________________________________________________________________^
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let a: &mut Vec<Ref<i32>> = x;
17 | | let b = Ref { data: y.data };
18 | | Vec::push(a, b);
@ -19,11 +18,10 @@ note: ...so that reference does not outlive borrowed content
|
17 | let b = Ref { data: y.data };
| ^^^^^^
note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66...
--> $DIR/ex2e-push-inference-variable-3.rs:15:67
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
--> $DIR/ex2e-push-inference-variable-3.rs:15:1
|
15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
| ___________________________________________________________________^
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let a: &mut Vec<Ref<i32>> = x;
17 | | let b = Ref { data: y.data };
18 | | Vec::push(a, b);