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
});
custom_kind
});
-impl_stable_hash_for!(struct ty::FreeRegion<'tcx> {
+impl_stable_hash_for!(struct ty::FreeRegion {
scope,
bound_region
});
}
};
- 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) {
}
pub fn add_given(&self,
- sub: ty::FreeRegion<'tcx>,
+ sub: ty::FreeRegion,
sup: ty::RegionVid)
{
self.region_vars.add_given(sub, sup);
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>),
// 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>>,
}
}
- 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());
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,
(&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)
}
// 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);
// 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
}));
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
}
}
}
+
+ /// 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`
use session::Session;
use hir::def::Def;
use hir::def_id::DefId;
-use middle::region;
use ty;
use std::cell::Cell;
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 {
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(..), ..
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());
}
_ => {}
}
};
// 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)
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,
}
}
-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>> {
//! 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};
/// 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>
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;
/// 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>>,
{
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()),
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()),
/// 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, _| {
// 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.
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
//
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)
}
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,
}
/// 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
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)
}
}
}
}
-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)
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,
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)
}
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));
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));
})
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));
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));
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),
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),
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));
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));
-> 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,
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};
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 {
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)
}))
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);
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={:?}",
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);
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
// 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> {
/// 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> {
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,
}
}
}
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()),
deferred_call_resolutions: RefCell::new(DefIdMap()),
deferred_cast_checks: RefCell::new(Vec::new()),
anon_types: RefCell::new(NodeMap()),
+ implicit_region_bound,
}
}
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);
}
fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
- let param_env = &self.parameter_environment;
-
debug!("param_bound(param_ty={:?})",
param_ty);
// 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)
}
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};
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));
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() {
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
})
}
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());
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
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);
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);
//~^ 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)
}
}
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 | | }
| |_^
|
= 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 | | }
| |_^
|
= 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 | | }
| |_^
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 | | }
|
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 | | }
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);
|
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);
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);
|
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);