From bd8246be744aa3620768e5e444527968f252e4fc Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 7 May 2017 16:22:33 +0300 Subject: [PATCH 01/10] rustc: uniformly compute ParameterEnvironment's "free outlive scope". --- src/librustc/infer/mod.rs | 6 +- src/librustc/middle/liveness.rs | 14 +- src/librustc/traits/specialize/mod.rs | 4 +- src/librustc/ty/context.rs | 15 ++- src/librustc/ty/layout.rs | 3 +- src/librustc/ty/mod.rs | 125 ++---------------- .../borrowck/mir/elaborate_drops.rs | 2 +- src/librustc_borrowck/borrowck/mir/mod.rs | 2 +- src/librustc_const_eval/check_match.rs | 7 +- src/librustc_lint/builtin.rs | 9 +- src/librustc_mir/build/mod.rs | 12 +- src/librustc_mir/shim.rs | 3 +- src/librustc_mir/transform/inline.rs | 3 +- src/librustc_mir/transform/qualify_consts.rs | 5 +- src/librustc_mir/transform/type_check.rs | 2 +- src/librustc_typeck/check/closure.rs | 2 +- src/librustc_typeck/check/compare_method.rs | 4 +- src/librustc_typeck/check/dropck.rs | 5 +- src/librustc_typeck/check/mod.rs | 11 +- src/librustc_typeck/check/regionck.rs | 5 +- src/librustc_typeck/check/wfcheck.rs | 13 +- src/librustc_typeck/coherence/builtin.rs | 5 +- 22 files changed, 70 insertions(+), 187 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index e91af21c6db..7959a38f26e 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -450,10 +450,10 @@ impl<'a, 'tcx> InferEnv<'a, 'tcx> for hir::BodyId { -> (Option<&'a ty::TypeckTables<'tcx>>, Option>, Option>) { - let item_id = tcx.hir.body_owner(self); - (Some(tcx.typeck_tables_of(tcx.hir.local_def_id(item_id))), + let def_id = tcx.hir.body_owner_def_id(self); + (Some(tcx.typeck_tables_of(def_id)), None, - Some(ty::ParameterEnvironment::for_item(tcx, item_id))) + Some(tcx.parameter_environment(def_id))) } } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 1ea87cc0a45..3acbc15f331 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -110,7 +110,7 @@ use self::LiveNodeKind::*; use self::VarKind::*; use hir::def::*; -use ty::{self, TyCtxt, ParameterEnvironment}; +use ty::{self, TyCtxt}; use traits::{self, Reveal}; use ty::subst::Subst; use lint; @@ -382,7 +382,7 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, // check for various error conditions lsets.visit_body(body); - lsets.check_ret(id, sp, entry_ln, body); + lsets.check_ret(id, sp, entry_ln); lsets.warn_about_unused_args(body, entry_ln); } @@ -1423,10 +1423,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn check_ret(&self, id: NodeId, sp: Span, - entry_ln: LiveNode, - body: &hir::Body) + entry_ln: LiveNode) { - let fn_ty = self.ir.tcx.type_of(self.ir.tcx.hir.local_def_id(id)); + let def_id = self.ir.tcx.hir.local_def_id(id); + let fn_ty = self.ir.tcx.type_of(def_id); let fn_sig = match fn_ty.sty { ty::TyClosure(closure_def_id, substs) => { self.ir.tcx.closure_type(closure_def_id) @@ -1441,11 +1441,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // 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, body.value.id)), + Some(self.ir.tcx.call_site_extent(id)), &fn_ret); if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() { - let param_env = ParameterEnvironment::for_item(self.ir.tcx, id); + let param_env = self.ir.tcx.parameter_environment(def_id); let t_ret_subst = fn_ret.subst(self.ir.tcx, ¶m_env.free_substs); let is_nil = self.ir.tcx.infer_ctxt(param_env, Reveal::All).enter(|infcx| { let cause = traits::ObligationCause::dummy(); diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index d5d17e3c812..f8d8f3962b8 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -179,9 +179,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.construct_parameter_environment(DUMMY_SP, - impl1_def_id, - None); + 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); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 74aac7b788b..54081c613cb 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -660,9 +660,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.intern_code_extent(CodeExtentData::DestructionScope(n)) } - pub fn call_site_extent(self, fn_id: ast::NodeId, body_id: ast::NodeId) -> CodeExtent<'gcx> { - assert!(fn_id != body_id); - self.intern_code_extent(CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id }) + pub fn call_site_extent(self, fn_id: ast::NodeId) -> CodeExtent<'gcx> { + self.intern_code_extent(CodeExtentData::CallSiteScope { + fn_id, + body_id: self.hir.body_owned_by(fn_id).node_id + }) + } + + pub fn parameter_extent(self, fn_id: ast::NodeId) -> CodeExtent<'gcx> { + self.intern_code_extent(CodeExtentData::ParameterScope { + fn_id, + body_id: self.hir.body_owned_by(fn_id).node_id + }) } pub fn intern_code_extent(self, data: CodeExtentData) -> CodeExtent<'gcx> { diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 480b8967a79..c3208e1dbfe 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1268,8 +1268,7 @@ impl<'a, 'gcx, 'tcx> Layout { let kind = if def.is_enum() || def.variants[0].fields.len() == 0{ StructKind::AlwaysSizedUnivariant } else { - let param_env = tcx.construct_parameter_environment(DUMMY_SP, - def.did, None); + 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) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index f5d510c11ae..0f20d2361c6 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1291,111 +1291,6 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { is_freeze_cache: RefCell::new(FxHashMap()), } } - - /// Construct a parameter environment given an item, impl item, or trait item - pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId) - -> ParameterEnvironment<'tcx> { - match tcx.hir.find(id) { - Some(hir_map::NodeImplItem(ref impl_item)) => { - match impl_item.node { - hir::ImplItemKind::Type(_) => { - // associated types don't have their own entry (for some reason), - // so for now just grab environment for the impl - let impl_id = tcx.hir.get_parent(id); - let impl_def_id = tcx.hir.local_def_id(impl_id); - tcx.construct_parameter_environment(impl_item.span, - impl_def_id, - Some(tcx.item_extent(id))) - } - hir::ImplItemKind::Const(_, body) | - hir::ImplItemKind::Method(_, body) => { - tcx.construct_parameter_environment( - impl_item.span, - tcx.hir.local_def_id(id), - Some(tcx.call_site_extent(id, body.node_id))) - } - } - } - Some(hir_map::NodeTraitItem(trait_item)) => { - match trait_item.node { - hir::TraitItemKind::Type(..) | - hir::TraitItemKind::Const(_, None) | - hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_))=> { - tcx.construct_parameter_environment(trait_item.span, - tcx.hir.local_def_id(id), - Some(tcx.item_extent(id))) - } - hir::TraitItemKind::Const(_, Some(body)) | - hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body)) => { - tcx.construct_parameter_environment( - trait_item.span, - tcx.hir.local_def_id(id), - Some(tcx.call_site_extent(id, body.node_id))) - } - } - } - Some(hir_map::NodeItem(item)) => { - match item.node { - hir::ItemConst(_, body) | - hir::ItemStatic(.., body) | - hir::ItemFn(.., body) => { - tcx.construct_parameter_environment( - item.span, - tcx.hir.local_def_id(id), - Some(tcx.call_site_extent(id, body.node_id))) - } - hir::ItemEnum(..) | - hir::ItemStruct(..) | - hir::ItemUnion(..) | - hir::ItemTy(..) | - hir::ItemImpl(..) | - hir::ItemTrait(..) => { - let def_id = tcx.hir.local_def_id(id); - tcx.construct_parameter_environment(item.span, - def_id, - Some(tcx.item_extent(id))) - } - _ => { - span_bug!(item.span, - "ParameterEnvironment::for_item(): - can't create a parameter \ - environment for this kind of item") - } - } - } - Some(hir_map::NodeExpr(expr)) => { - // This is a convenience to allow closures to work. - if let hir::ExprClosure(.., body, _) = expr.node { - let def_id = tcx.hir.local_def_id(id); - let base_def_id = tcx.closure_base_def_id(def_id); - tcx.construct_parameter_environment( - expr.span, - base_def_id, - Some(tcx.call_site_extent(id, body.node_id))) - } else { - tcx.empty_parameter_environment() - } - } - Some(hir_map::NodeForeignItem(item)) => { - let def_id = tcx.hir.local_def_id(id); - tcx.construct_parameter_environment(item.span, - def_id, - None) - } - Some(hir_map::NodeStructCtor(..)) | - Some(hir_map::NodeVariant(..)) => { - let def_id = tcx.hir.local_def_id(id); - tcx.construct_parameter_environment(tcx.hir.span(id), - def_id, - None) - } - it => { - bug!("ParameterEnvironment::from_item(): \ - `{}` = {:?} is unsupported", - tcx.hir.node_to_string(id), it) - } - } - } } #[derive(Copy, Clone, Debug)] @@ -2528,23 +2423,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.global_tcx().mk_param_from_def(def) }); - debug!("construct_parameter_environment: {:?}", substs); + debug!("parameter_environment: {:?}", substs); substs } /// See `ParameterEnvironment` struct def'n for details. - /// If you were using `free_id: NodeId`, you might try `self.region_maps().item_extent(free_id)` - /// for the `free_id_outlive` parameter. (But note that this is not always quite right.) - pub fn construct_parameter_environment(self, - span: Span, - def_id: DefId, - free_id_outlive: Option>) - -> ParameterEnvironment<'gcx> - { + pub fn parameter_environment(self, def_id: DefId) -> ParameterEnvironment<'gcx> { // // 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); // @@ -2582,7 +2477,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let body_id = free_id_outlive.map(|f| f.node_id()) .unwrap_or(DUMMY_NODE_ID); - let cause = traits::ObligationCause::misc(span, body_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) } diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index 4b7d52c2517..520a90d940b 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -44,7 +44,7 @@ impl MirPass for ElaborateDrops { _ => return } let id = src.item_id(); - let param_env = ty::ParameterEnvironment::for_item(tcx, id); + let param_env = tcx.parameter_environment(tcx.hir.local_def_id(id)); let move_data = MoveData::gather_moves(mir, tcx, ¶m_env); let elaborate_patch = { let mir = &*mir; diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs index 47f708bf583..fbaa60f8445 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/mod.rs @@ -65,7 +65,7 @@ pub fn borrowck_mir(bcx: &mut BorrowckCtxt, // steals it, but it forces the `borrowck` query. let mir = &tcx.mir_validated(def_id).borrow(); - let param_env = ty::ParameterEnvironment::for_item(tcx, id); + let param_env = tcx.parameter_environment(def_id); let move_data = MoveData::gather_moves(mir, tcx, ¶m_env); let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index cd31290eb55..a3dab6a938d 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -46,14 +46,13 @@ impl<'a, 'tcx> Visitor<'tcx> for OuterVisitor<'a, 'tcx> { b: hir::BodyId, s: Span, id: ast::NodeId) { intravisit::walk_fn(self, fk, fd, b, s, id); - let region_context = self.tcx.hir.local_def_id(id); - let region_maps = self.tcx.region_maps(region_context); + let def_id = self.tcx.hir.local_def_id(id); MatchVisitor { tcx: self.tcx, tables: self.tcx.body_tables(b), - region_maps: ®ion_maps, - param_env: &ty::ParameterEnvironment::for_item(self.tcx, id) + region_maps: &self.tcx.region_maps(def_id), + param_env: &self.tcx.parameter_environment(def_id) }.visit_body(self.tcx.hir.body(b)); } } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 3b6516af35a..6423d65a4c2 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -990,12 +990,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { traits::Obligation::new(traits::ObligationCause::misc(span, expr_id), trait_ref.to_poly_trait_predicate()); - // unwrap() is ok here b/c `method` is the method - // defined in this crate whose body we are - // checking, so it's always local - let node_id = tcx.hir.as_local_node_id(method.def_id).unwrap(); - - let param_env = ty::ParameterEnvironment::for_item(tcx, node_id); + let param_env = tcx.parameter_environment(method.def_id); tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| { let mut selcx = traits::SelectionContext::new(&infcx); match selcx.select(&obligation) { @@ -1263,7 +1258,7 @@ impl LintPass for UnionsWithDropFields { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields { fn check_item(&mut self, ctx: &LateContext, item: &hir::Item) { if let hir::ItemUnion(ref vdata, _) = item.node { - let param_env = &ty::ParameterEnvironment::for_item(ctx.tcx, item.id); + let param_env = &ctx.tcx.parameter_environment(ctx.tcx.hir.local_def_id(item.id)); for field in vdata.fields() { let field_ty = ctx.tcx.type_of(ctx.tcx.hir.local_def_id(field.id)); if field_ty.needs_drop(ctx.tcx, param_env) { diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 8c057b02df2..1634aade0bc 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -14,7 +14,7 @@ use hair::cx::Cx; use hair::Pattern; use rustc::hir; use rustc::hir::def_id::DefId; -use rustc::middle::region::{CodeExtent, CodeExtentData}; +use rustc::middle::region::CodeExtent; use rustc::mir::*; use rustc::mir::transform::MirSource; use rustc::mir::visit::MutVisitor; @@ -172,7 +172,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let span = tcx.hir.span(ctor_id); if let hir::VariantData::Tuple(ref fields, ctor_id) = *v { - let pe = ty::ParameterEnvironment::for_item(tcx, ctor_id); + let pe = tcx.parameter_environment(tcx.hir.local_def_id(ctor_id)); tcx.infer_ctxt(pe, Reveal::UserFacing).enter(|infcx| { let (mut mir, src) = shim::build_adt_ctor(&infcx, ctor_id, fields, span); @@ -337,12 +337,8 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let span = tcx.hir.span(fn_id); let mut builder = Builder::new(hir.clone(), span, arguments.len(), return_ty); - let call_site_extent = - tcx.intern_code_extent( - CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body.value.id }); - let arg_extent = - tcx.intern_code_extent( - CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.value.id }); + let call_site_extent = tcx.call_site_extent(fn_id); + let arg_extent = tcx.parameter_extent(fn_id); let mut block = START_BLOCK; unpack!(block = builder.in_scope(call_site_extent, block, |builder| { unpack!(block = builder.in_scope(arg_extent, block, |builder| { diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index a6f9952b23c..587cc27f4b8 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -41,8 +41,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, { debug!("make_shim({:?})", instance); let did = instance.def_id(); - let span = tcx.def_span(did); - let param_env = tcx.construct_parameter_environment(span, did, None); + let param_env = tcx.parameter_environment(did); let mut result = match instance { ty::InstanceDef::Item(..) => diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index f60dcbed6ba..e6d62dc6460 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -219,7 +219,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { // FIXME: Give a bonus to functions with only a single caller - let param_env = ty::ParameterEnvironment::for_item(tcx, self.source.item_id()); + let def_id = tcx.hir.local_def_id(self.source.item_id()); + let param_env = tcx.parameter_environment(def_id); let mut first_block = true; let mut cost = 0; diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index df837a32133..72edf68f403 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -937,8 +937,7 @@ fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return Qualif::NOT_CONST.bits(); } - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let param_env = ty::ParameterEnvironment::for_item(tcx, node_id); + let param_env = tcx.parameter_environment(def_id); let mut qualifier = Qualifier::new(tcx, param_env, def_id, mir, Mode::Const); qualifier.qualify_const().bits() @@ -966,7 +965,7 @@ impl MirPass for QualifyAndPromoteConstants { MirSource::Const(_) | MirSource::Promoted(..) => return }; - let param_env = ty::ParameterEnvironment::for_item(tcx, id); + let param_env = tcx.parameter_environment(def_id); if mode == Mode::Fn || mode == Mode::ConstFn { // This is ugly because Qualifier holds onto mir, diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index be384218a41..82c0d2c1b01 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -751,7 +751,7 @@ impl MirPass for TypeckMir { // broken MIR, so try not to report duplicate errors. return; } - let param_env = ty::ParameterEnvironment::for_item(tcx, item_id); + let param_env = tcx.parameter_environment(def_id); tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| { let mut checker = TypeChecker::new(&infcx, item_id); { diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index fb3be849319..c234629e528 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -73,7 +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, body.value.id); + 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.inh.normalize_associated_types_in(body.value.span, body.value.id, &fn_sig); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 0579bb15fd6..034d718723d 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -167,7 +167,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Create a parameter environment that represents the implementation's // method. - let impl_param_env = ty::ParameterEnvironment::for_item(tcx, impl_m_node_id); + 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; @@ -739,7 +739,7 @@ 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 = ty::ParameterEnvironment::for_item(tcx, impl_c_node_id); + 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; diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index c20777a403a..f6ffb3c0135 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -76,11 +76,10 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( -> Result<(), ErrorReported> { let drop_impl_node_id = tcx.hir.as_local_node_id(drop_impl_did).unwrap(); - let self_type_node_id = tcx.hir.as_local_node_id(self_type_did).unwrap(); // check that the impl type can be made to match the trait type. - let impl_param_env = ty::ParameterEnvironment::for_item(tcx, self_type_node_id); + let impl_param_env = tcx.parameter_environment(self_type_did); tcx.infer_ctxt(impl_param_env, Reveal::UserFacing).enter(|ref infcx| { let tcx = infcx.tcx; let mut fulfillment_cx = traits::FulfillmentContext::new(); @@ -99,7 +98,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( fulfillment_cx.register_predicate_obligations(infcx, obligations); } Err(_) => { - let item_span = tcx.hir.span(self_type_node_id); + let item_span = tcx.def_span(self_type_did); struct_span_err!(tcx.sess, drop_impl_span, E0366, "Implementations of Drop cannot be specialized") .span_note(item_span, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 127ffc60cf4..f632d090b41 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -90,8 +90,7 @@ use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin}; use rustc::infer::type_variable::{TypeVariableOrigin}; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal}; -use rustc::ty::{ParamTy, ParameterEnvironment}; -use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue}; +use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue}; use rustc::ty::{self, Ty, TyCtxt, Visibility}; use rustc::ty::{MethodCall, MethodCallee}; use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; @@ -527,10 +526,10 @@ pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { - pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId) + pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId) -> InheritedBuilder<'a, 'gcx, 'tcx> { let tables = ty::TypeckTables::empty(); - let param_env = ParameterEnvironment::for_item(tcx, id); + let param_env = tcx.parameter_environment(def_id); InheritedBuilder { infcx: tcx.infer_ctxt((tables, param_env), Reveal::UserFacing) } @@ -772,14 +771,14 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }); let body = tcx.hir.body(body_id); - Inherited::build(tcx, id).enter(|inh| { + Inherited::build(tcx, def_id).enter(|inh| { let fcx = if let Some(decl) = fn_decl { let fn_sig = tcx.type_of(def_id).fn_sig(); 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, body_id.node_id); + 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 = diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index e4936dfc47b..261845c793c 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -87,7 +87,7 @@ use check::FnCtxt; use middle::free_region::FreeRegionMap; use middle::mem_categorization as mc; use middle::mem_categorization::Categorization; -use middle::region::{self, CodeExtent, RegionMaps}; +use middle::region::{CodeExtent, RegionMaps}; use rustc::hir::def_id::DefId; use rustc::ty::subst::Substs; use rustc::traits; @@ -286,8 +286,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let body_id = body.id(); - let call_site = self.tcx.intern_code_extent( - region::CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id }); + let call_site = self.tcx.call_site_extent(id); let old_call_site_scope = self.set_call_site_scope(Some(call_site)); let fn_sig = { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 93529aecac0..5d8ac32e09e 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -117,8 +117,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { error_192(tcx, item.span); } } - hir::ItemFn(.., body_id) => { - self.check_item_fn(item, body_id); + hir::ItemFn(..) => { + self.check_item_fn(item); } hir::ItemStatic(..) => { self.check_item_type(item); @@ -210,7 +210,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { fn for_id<'tcx>(&self, id: ast::NodeId, span: Span) -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { CheckWfFcxBuilder { - inherited: Inherited::build(self.tcx, id), + inherited: Inherited::build(self.tcx, self.tcx.hir.local_def_id(id)), code: self.code.clone(), id: id, span: span @@ -327,10 +327,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { }); } - fn check_item_fn(&mut self, - item: &hir::Item, - body_id: hir::BodyId) - { + 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); @@ -341,7 +338,7 @@ 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, body_id.node_id); + 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); implied_bounds diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 743bfbb44ab..47642798617 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -17,7 +17,6 @@ use rustc::middle::lang_items::UnsizeTraitLangItem; use rustc::traits::{self, ObligationCause, Reveal}; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::ParameterEnvironment; use rustc::ty::TypeFoldable; use rustc::ty::adjustment::CoerceUnsizedInfo; use rustc::ty::subst::Subst; @@ -107,7 +106,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, self_type); let span = tcx.hir.span(impl_node_id); - let param_env = ParameterEnvironment::for_item(tcx, 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()); @@ -202,7 +201,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, target); let span = tcx.hir.span(impl_node_id); - let param_env = ParameterEnvironment::for_item(tcx, 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()); From 9809fe0d021ebed29d13a4f7fa58c660107da384 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 7 May 2017 16:49:03 +0300 Subject: [PATCH 02/10] rustc: use call_site_extent for closure environment free regions. --- src/librustc/middle/mem_categorization.rs | 16 +--------------- src/librustc_mir/build/mod.rs | 2 +- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 11a364f92c3..c489689d588 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -785,26 +785,12 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { cmt_result: cmt_<'tcx>) -> cmt_<'tcx> { - // Look up the node ID of the closure body so we can construct - // a free region within it - let fn_body_id = { - let fn_expr = match self.tcx().hir.find(upvar_id.closure_expr_id) { - Some(hir_map::NodeExpr(e)) => e, - _ => bug!() - }; - - match fn_expr.node { - hir::ExprClosure(.., body_id, _) => body_id, - _ => bug!() - } - }; - // Region of environment pointer let env_region = self.tcx().mk_region(ty::ReFree(ty::FreeRegion { // The environment of a closure is guaranteed to // outlive any bindings introduced in the body of the // closure itself. - scope: Some(self.tcx().item_extent(fn_body_id.node_id)), + scope: Some(self.tcx().call_site_extent(upvar_id.closure_expr_id)), bound_region: ty::BrEnv })); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 1634aade0bc..cecfd6e4c24 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -207,7 +207,7 @@ fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_id); let region = ty::ReFree(ty::FreeRegion { - scope: Some(tcx.item_extent(body_id.node_id)), + scope: Some(tcx.call_site_extent(closure_expr_id)), bound_region: ty::BoundRegion::BrEnv, }); let region = tcx.mk_region(region); From 72aab7ade4e333896f4a553ad59b73346dcd8f43 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 7 May 2017 17:30:55 +0300 Subject: [PATCH 03/10] rustc_mir: remove unnecessary drop scope for constants. --- src/librustc_mir/build/mod.rs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index cecfd6e4c24..b441f509b53 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -401,22 +401,15 @@ pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, let span = tcx.hir.span(owner_id); let mut builder = Builder::new(hir.clone(), span, 0, ty); - let extent = hir.region_maps.temporary_scope(tcx, ast_expr.id) - .unwrap_or(tcx.item_extent(owner_id)); let mut block = START_BLOCK; - let _ = builder.in_scope(extent, block, |builder| { - let expr = builder.hir.mirror(ast_expr); - unpack!(block = builder.into(&Lvalue::Local(RETURN_POINTER), block, expr)); + let expr = builder.hir.mirror(ast_expr); + unpack!(block = builder.into_expr(&Lvalue::Local(RETURN_POINTER), block, expr)); - let source_info = builder.source_info(span); - let return_block = builder.return_block(); - builder.cfg.terminate(block, source_info, - TerminatorKind::Goto { target: return_block }); - builder.cfg.terminate(return_block, source_info, - TerminatorKind::Return); + let source_info = builder.source_info(span); + builder.cfg.terminate(block, source_info, TerminatorKind::Return); - return_block.unit() - }); + // Constants can't `return` so a return block should not be created. + assert_eq!(builder.cached_return_block, None); builder.finish(vec![], ty) } From 6d4c2141b5042bd9469005444987f5fb3f20fa73 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 7 May 2017 19:57:51 +0300 Subject: [PATCH 04/10] rustc: use DefId instead of CodeExtent for FreeRegion's scope. --- src/librustc/ich/impls_ty.rs | 7 +-- src/librustc/infer/error_reporting/mod.rs | 2 +- src/librustc/infer/mod.rs | 2 +- src/librustc/infer/region_inference/mod.rs | 27 +++++----- src/librustc/middle/free_region.rs | 9 ++-- src/librustc/middle/liveness.rs | 4 +- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/region.rs | 25 +++------- src/librustc/middle/resolve_lifetime.rs | 9 ++-- src/librustc/traits/object_safety.rs | 2 +- src/librustc/ty/context.rs | 14 ------ src/librustc/ty/fold.rs | 4 +- src/librustc/ty/mod.rs | 49 +++---------------- src/librustc/ty/sty.rs | 10 ++-- src/librustc/util/ppaux.rs | 4 +- .../borrowck/gather_loans/mod.rs | 4 +- src/librustc_driver/test.rs | 28 +++++------ src/librustc_mir/build/mod.rs | 5 +- src/librustc_mir/hair/cx/expr.rs | 20 ++------ src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/check/closure.rs | 3 +- src/librustc_typeck/check/compare_method.rs | 6 +-- src/librustc_typeck/check/mod.rs | 34 ++++++++++--- src/librustc_typeck/check/regionck.rs | 4 +- src/librustc_typeck/check/wfcheck.rs | 19 +++---- src/test/compile-fail/issue-37884.rs | 4 +- ...x1-return-one-existing-name-if-else.stderr | 14 +++--- .../ex2a-push-one-existing-name.stderr | 14 +++--- .../ex2b-push-no-existing-names.stderr | 14 +++--- .../ex2c-push-inference-variable.stderr | 14 +++--- .../ex2d-push-inference-variable-2.stderr | 14 +++--- .../ex2e-push-inference-variable-3.stderr | 14 +++--- 32 files changed, 149 insertions(+), 234 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 52bdb5d0240..f822361198f 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -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 }); diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 4c27bade0f7..389103e203e 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -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) { diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 7959a38f26e..23d720433c2 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -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); diff --git a/src/librustc/infer/region_inference/mod.rs b/src/librustc/infer/region_inference/mod.rs index 39554d1fa3a..4c82c3bfb85 100644 --- a/src/librustc/infer/region_inference/mod.rs +++ b/src/librustc/infer/region_inference/mod.rs @@ -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, ty::RegionVid)>>, + givens: RefCell>, lubs: RefCell>, glbs: RefCell>, @@ -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, diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs index 2dc7aac04ae..e0d13878f14 100644 --- a/src/librustc/middle/free_region.rs +++ b/src/librustc/middle/free_region.rs @@ -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) } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 3acbc15f331..732fb054bc4 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -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); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index c489689d588..8e25c6facf2 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -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 })); diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 087ab4b94da..3f707ac95f7 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -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` diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 67b8dfb2d8e..55770efa9ad 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -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()); } _ => {} } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index ea1a2f9a982..dbc1f070af8 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -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) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 54081c613cb..d69a9b3a8ce 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -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 { - 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> { diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 21ccf6f987b..fc20b1bee4e 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -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(self, - all_outlive_scope: Option>, + all_outlive_scope: DefId, value: &Binder) -> T where T : TypeFoldable<'tcx> diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 0f20d2361c6..4b10ec67def 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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>, - /// 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>, - /// A cache for `moves_by_default`. pub is_copy_cache: RefCell, 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>) - -> &'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) } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 89960b0e4f6..1b09baccadb 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -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>, +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 diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index d773bb2da08..307897c4eb4 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -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) diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 8c1bcdc1fe2..ca0e5dad65b 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -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, diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 3b4f2560fc5..e8885626151 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -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)); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index b441f509b53..a3b1b24f20a 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -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, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 6a1817aba09..a692e987761 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -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 { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index adcb3d682ca..dfcc68bf390 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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) })) diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index c234629e528..dc1aa9f8592 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -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); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 034d718723d..9248415ad5b 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -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 diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f632d090b41..7861aa09d0f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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>>, + + /// 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>, } 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(&'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); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 261845c793c..bdaf3db8780 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -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) } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 5d8ac32e09e..225d0ce0765 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -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>, + def_id: DefId, implied_bounds: &mut Vec>) { 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>, 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); diff --git a/src/test/compile-fail/issue-37884.rs b/src/test/compile-fail/issue-37884.rs index 6e1b9b2fbed..28ce79ab5aa 100644 --- a/src/test/compile-fail/issue-37884.rs +++ b/src/test/compile-fail/issue-37884.rs @@ -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) } } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr index cf272b63128..55723ee8cd9 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr @@ -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 | | } | |_^ diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr index 6e03e66dd25..b7d985feca9 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr @@ -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>, y: Ref) { - | ____________________________________________________^ +15 | / fn foo<'a>(x: &mut Vec>, y: Ref) { 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>, y: Ref) { - | ____________________________________________________^ +15 | / fn foo<'a>(x: &mut Vec>, y: Ref) { 16 | | x.push(y); 17 | | } | |_^ diff --git a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr index 028f54ce978..3a6e94f2b1c 100644 --- a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr +++ b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr @@ -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>, y: Ref) { - | ____________________________________________^ +15 | / fn foo(x: &mut Vec>, y: Ref) { 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>, y: Ref) { - | ____________________________________________^ +15 | / fn foo(x: &mut Vec>, y: Ref) { 16 | | x.push(y); 17 | | } | |_^ diff --git a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr index 4621214419e..3d7064a4f71 100644 --- a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr +++ b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr @@ -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>, y: Ref<'c, i32>) { - | ___________________________________________________________________^ +15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec>, 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>, y: Ref<'c, i32>) { - | ___________________________________________________________________^ +15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { 16 | | let z = Ref { data: y.data }; 17 | | x.push(z); 18 | | } diff --git a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr index a69694fdc2e..aced855bf66 100644 --- a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr +++ b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr @@ -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>, y: Ref<'c, i32>) { - | ___________________________________________________________________^ +15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { 16 | | let a: &mut Vec> = 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>, y: Ref<'c, i32>) { - | ___________________________________________________________________^ +15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { 16 | | let a: &mut Vec> = x; 17 | | let b = Ref { data: y.data }; 18 | | a.push(b); diff --git a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr index eff15bb794b..07e2316b63d 100644 --- a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr +++ b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr @@ -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>, y: Ref<'c, i32>) { - | ___________________________________________________________________^ +15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { 16 | | let a: &mut Vec> = 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>, y: Ref<'c, i32>) { - | ___________________________________________________________________^ +15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { 16 | | let a: &mut Vec> = x; 17 | | let b = Ref { data: y.data }; 18 | | Vec::push(a, b); From 74c6788d9c1d08e13de9ae7528c720d145c7d9da Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 10 May 2017 13:40:59 +0300 Subject: [PATCH 05/10] rustc: move liberate_late_bound_regions to rustc_typeck. --- src/librustc/middle/liveness.rs | 49 +-------------------- src/librustc/ty/fold.rs | 18 -------- src/librustc/ty/mod.rs | 1 - src/librustc_typeck/check/closure.rs | 2 +- src/librustc_typeck/check/compare_method.rs | 2 +- src/librustc_typeck/check/mod.rs | 18 +++++++- src/librustc_typeck/check/wfcheck.rs | 8 ++-- 7 files changed, 24 insertions(+), 74 deletions(-) diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 732fb054bc4..ecd350d1273 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -96,9 +96,6 @@ //! //! - `fallthrough_ln`: a live node that represents a fallthrough //! -//! - `no_ret_var`: a synthetic variable that is only 'read' from, the -//! fallthrough node. This allows us to detect functions where we fail -//! to return explicitly. //! - `clean_exit_var`: a synthetic variable that is only 'read' from the //! fallthrough node. It is only live if the function could converge //! via means other than an explicit `return` expression. That is, it is @@ -111,8 +108,6 @@ use self::VarKind::*; use hir::def::*; use ty::{self, TyCtxt}; -use traits::{self, Reveal}; -use ty::subst::Subst; use lint; use util::nodemap::NodeMap; @@ -256,7 +251,6 @@ struct LocalInfo { enum VarKind { Arg(NodeId, ast::Name), Local(LocalInfo), - ImplicitRet, CleanExit } @@ -313,7 +307,7 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> { Local(LocalInfo { id: node_id, .. }) | Arg(node_id, _) => { self.variable_map.insert(node_id, v); }, - ImplicitRet | CleanExit => {} + CleanExit => {} } debug!("{:?} is {:?}", v, vk); @@ -335,7 +329,6 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> { Local(LocalInfo { name, .. }) | Arg(_, name) => { name.to_string() }, - ImplicitRet => "".to_string(), CleanExit => "".to_string() } } @@ -382,7 +375,6 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, // check for various error conditions lsets.visit_body(body); - lsets.check_ret(id, sp, entry_ln); lsets.warn_about_unused_args(body, entry_ln); } @@ -500,7 +492,6 @@ fn invalid_users() -> Users { struct Specials { exit_ln: LiveNode, fallthrough_ln: LiveNode, - no_ret_var: Variable, clean_exit_var: Variable } @@ -534,7 +525,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let specials = Specials { exit_ln: ir.add_live_node(ExitNode), fallthrough_ln: ir.add_live_node(ExitNode), - no_ret_var: ir.add_variable(ImplicitRet), clean_exit_var: ir.add_variable(CleanExit) }; @@ -1420,43 +1410,6 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { } impl<'a, 'tcx> Liveness<'a, 'tcx> { - fn check_ret(&self, - id: NodeId, - sp: Span, - entry_ln: LiveNode) - { - let def_id = self.ir.tcx.hir.local_def_id(id); - let fn_ty = self.ir.tcx.type_of(def_id); - let fn_sig = match fn_ty.sty { - ty::TyClosure(closure_def_id, substs) => { - self.ir.tcx.closure_type(closure_def_id) - .subst(self.ir.tcx, substs.substs) - } - _ => fn_ty.fn_sig() - }; - - let fn_ret = fn_sig.output(); - - // 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(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); - let t_ret_subst = fn_ret.subst(self.ir.tcx, ¶m_env.free_substs); - let is_nil = self.ir.tcx.infer_ctxt(param_env, Reveal::All).enter(|infcx| { - let cause = traits::ObligationCause::dummy(); - traits::fully_normalize(&infcx, cause, &t_ret_subst).unwrap().is_nil() - }); - - // for nil return types, it is ok to not return a value expl. - if !is_nil { - span_bug!(sp, "not all control paths return a value"); - } - } - } - fn check_lvalue(&mut self, expr: &'tcx Expr) { match expr.node { hir::ExprPath(hir::QPath::Resolved(_, ref path)) => { diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index fc20b1bee4e..6820b9af940 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -39,7 +39,6 @@ //! 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 hir::def_id::DefId; use ty::subst::Substs; use ty::adjustment; use ty::{self, Binder, Ty, TyCtxt, TypeFlags}; @@ -326,23 +325,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { (result, replacer.map) } - - /// Replace any late-bound regions bound in `value` with free variants attached to scope-id - /// `scope_id`. - pub fn liberate_late_bound_regions(self, - all_outlive_scope: DefId, - value: &Binder) - -> T - where T : TypeFoldable<'tcx> - { - self.replace_late_bound_regions(value, |br| { - self.mk_region(ty::ReFree(ty::FreeRegion { - scope: all_outlive_scope, - bound_region: br - })) - }).0 - } - /// Flattens two binding levels into one. So `for<'a> for<'b> Foo` /// becomes `for<'a,'b> Foo`. pub fn flatten_late_bound_regions(self, bound2_value: &Binder>) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4b10ec67def..99ee4e41d1d 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2417,7 +2417,6 @@ 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(def_id, &ty::Binder(bounds)); let predicates = bounds.predicates; // Finally, we have to normalize the bounds in the environment, in diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index dc1aa9f8592..9eca2b96d62 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -73,7 +73,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type); - let fn_sig = self.tcx.liberate_late_bound_regions(expr_def_id, &sig); + let fn_sig = self.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); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 9248415ad5b..7404222a4bd 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -282,7 +282,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let impl_fty = tcx.mk_fn_ptr(ty::Binder(impl_sig)); debug!("compare_impl_method: impl_fty={:?}", impl_fty); - let trait_sig = tcx.liberate_late_bound_regions( + let trait_sig = inh.liberate_late_bound_regions( impl_m.def_id, &m_sig(trait_m)); let trait_sig = diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7861aa09d0f..201fc6ce7f2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -628,6 +628,22 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { obligations); InferOk { value, obligations } } + + /// Replace any late-bound regions bound in `value` with + /// free variants attached to `all_outlive_scope`. + fn liberate_late_bound_regions(&self, + all_outlive_scope: DefId, + value: &ty::Binder) + -> T + where T: TypeFoldable<'tcx> + { + self.tcx.replace_late_bound_regions(value, |br| { + self.tcx.mk_region(ty::ReFree(ty::FreeRegion { + scope: all_outlive_scope, + bound_region: br + })) + }).0 + } } struct CheckItemTypesVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> } @@ -804,7 +820,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let fn_sig = fn_sig.subst(inh.tcx, &inh.parameter_environment.free_substs); let fn_sig = - inh.tcx.liberate_late_bound_regions(def_id, &fn_sig); + inh.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); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 225d0ce0765..af7830a63a7 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -427,7 +427,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { { 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(def_id, &sig); + let sig = fcx.liberate_late_bound_regions(def_id, &sig); for input_ty in sig.inputs() { fcx.register_wf_obligation(&input_ty, span, self.code.clone()); @@ -462,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(method.def_id, &fty.fn_sig()); + let sig = fcx.liberate_late_bound_regions(method.def_id, &fty.fn_sig()); debug!("check_method_receiver: sig={:?}", sig); @@ -478,8 +478,8 @@ 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(method.def_id, - &ty::Binder(rcvr_ty)); + let rcvr_ty = fcx.liberate_late_bound_regions(method.def_id, + &ty::Binder(rcvr_ty)); debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty); From dbae169ac16de632d21fd3394bc8a939b2524512 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 10 May 2017 16:59:41 +0300 Subject: [PATCH 06/10] rustc_typeck: do not leak late-bound lifetimes from bounds to closures. --- src/librustc/middle/region.rs | 58 +++++++++++++++++++++++++++- src/librustc/ty/mod.rs | 4 +- src/librustc_typeck/check/closure.rs | 3 ++ 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 3f707ac95f7..c6565b78f61 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -198,6 +198,14 @@ impl CodeExtentData { /// The region maps encode information about region relationships. pub struct RegionMaps<'tcx> { + /// If not empty, this body is the root of this region hierarchy. + root_body: Option, + + /// The parent of the root body owner, if the latter is an + /// an associated const or method, as impls/traits can also + /// have lifetime parameters free in this body. + root_parent: Option, + /// `scope_map` maps from a scope id to the enclosing scope id; /// this is usually corresponding to the lexical nesting, though /// in the case of closures the parent scope is the innermost @@ -295,6 +303,8 @@ struct RegionResolutionVisitor<'a, 'tcx: 'a> { impl<'tcx> RegionMaps<'tcx> { pub fn new() -> Self { RegionMaps { + root_body: None, + root_parent: None, scope_map: FxHashMap(), destruction_scopes: FxHashMap(), var_map: NodeMap(), @@ -600,8 +610,39 @@ impl<'tcx> RegionMaps<'tcx> { /// 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) + let param_owner = match fr.bound_region { + ty::BoundRegion::BrNamed(def_id, _) => { + tcx.parent_def_id(def_id).unwrap() + } + _ => 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 + }); + + tcx.intern_code_extent(CodeExtentData::CallSiteScope { + fn_id: tcx.hir.body_owner(body_id), + body_id: body_id.node_id + }) } } @@ -1167,6 +1208,19 @@ fn region_maps<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) let id = tcx.hir.as_local_node_id(def_id).unwrap(); if let Some(body) = tcx.hir.maybe_body_owned_by(id) { + maps.root_body = Some(body); + + // If the item is an associated const or a method, + // record its impl/trait parent, as it can also have + // lifetime parameters free in this body. + match tcx.hir.get(id) { + hir::map::NodeImplItem(_) | + hir::map::NodeTraitItem(_) => { + maps.root_parent = Some(tcx.hir.get_parent(id)); + } + _ => {} + } + let mut visitor = RegionResolutionVisitor { tcx: tcx, region_maps: &mut maps, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 99ee4e41d1d..8ccaf0622d7 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2386,11 +2386,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// 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: def_id, + scope, bound_region: def.to_bound_region() })) }, |def, _| { diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 9eca2b96d62..9e4a7ed1ddc 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -60,6 +60,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { decl, Abi::RustCall, expected_sig); + // `deduce_expectations_from_expected_type` introduces late-bound + // lifetimes defined elsewhere, which we need to anonymize away. + let sig = self.tcx.anonymize_late_bound_regions(&sig); // Create type variables (for now) to represent the transformed // types of upvars. These will be unified during the upvar From 2da080e779b4e6f4359c031824c3bdcedad452fd Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 May 2017 15:05:00 +0300 Subject: [PATCH 07/10] rustc: treat ReEarlyBound as free without replacing it with ReFree. --- src/librustc/ich/impls_ty.rs | 3 +- src/librustc/infer/combine.rs | 10 +-- src/librustc/infer/error_reporting/mod.rs | 41 ++++++++---- src/librustc/infer/freshen.rs | 2 +- src/librustc/infer/higher_ranked/mod.rs | 8 +-- src/librustc/infer/mod.rs | 2 +- src/librustc/infer/region_inference/mod.rs | 63 ++++++++++------- src/librustc/middle/free_region.rs | 67 +++++++++---------- src/librustc/middle/region.rs | 52 ++++++++------ src/librustc/middle/resolve_lifetime.rs | 4 +- src/librustc/traits/object_safety.rs | 3 +- src/librustc/traits/specialize/mod.rs | 4 +- src/librustc/traits/util.rs | 4 +- src/librustc/ty/layout.rs | 2 +- src/librustc/ty/mod.rs | 59 +++++++--------- src/librustc/ty/outlives.rs | 2 +- src/librustc/ty/sty.rs | 4 +- src/librustc/ty/util.rs | 5 +- src/librustc/util/ppaux.rs | 6 +- .../borrowck/gather_loans/mod.rs | 5 +- src/librustc_borrowck/borrowck/mod.rs | 2 + src/librustc_driver/test.rs | 5 +- src/librustc_mir/shim.rs | 15 ++--- src/librustc_typeck/astconv.rs | 20 +----- src/librustc_typeck/check/closure.rs | 5 +- src/librustc_typeck/check/compare_method.rs | 37 +++------- src/librustc_typeck/check/dropck.rs | 1 - src/librustc_typeck/check/mod.rs | 6 -- src/librustc_typeck/check/regionck.rs | 8 ++- src/librustc_typeck/check/wfcheck.rs | 60 +++++++---------- src/librustc_typeck/check/writeback.rs | 60 +++-------------- src/librustc_typeck/coherence/builtin.rs | 4 -- src/librustc_typeck/collect.rs | 5 +- src/test/compile-fail/issue-27942.rs | 7 +- src/test/compile-fail/issue-37884.rs | 3 +- 35 files changed, 250 insertions(+), 334 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index f822361198f..f9a86c2f010 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -54,7 +54,8 @@ impl<'a, 'tcx> HashStable> 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); } diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 82578f6aa61..18909a784d6 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -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), diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 389103e203e..da5ff6ff38a 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -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, diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index ad67ef9a127..a0ef1f65f52 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -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(_) | diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index 09f909ef399..dbbcc6cfbec 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -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: diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 23d720433c2..e42280124a1 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -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); diff --git a/src/librustc/infer/region_inference/mod.rs b/src/librustc/infer/region_inference/mod.rs index 4c82c3bfb85..2e3c2443544 100644 --- a/src/librustc/infer/region_inference/mod.rs +++ b/src/librustc/infer/region_inference/mod.rs @@ -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>, + givens: RefCell, ty::RegionVid)>>, lubs: RefCell>, glbs: RefCell>, @@ -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 { diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs index e0d13878f14..8168837b1f5 100644 --- a/src/librustc/middle/free_region.rs +++ b/src/librustc/middle/free_region.rs @@ -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 }); diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index c6565b78f61..917b21c865a 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -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), diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 55770efa9ad..7d7308d73bb 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -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 { diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index dbc1f070af8..66e8e503be4 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -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 { diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index f8d8f3962b8..3882e218241 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -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| { diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 1d10c3a9695..3f5cf7eca53 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -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( diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index c3208e1dbfe..bd38a6c3fd3 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -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 } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8ccaf0622d7..51bd0b88bac 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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()), diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index a544b2dd399..ab1b1b3857d 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -204,7 +204,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { fn push_region_constraints<'tcx>(out: &mut Vec>, regions: Vec>) { for r in regions { - if !r.is_bound() { + if !r.is_late_bound() { out.push(Component::Region(r)); } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 1b09baccadb..4faefc0fca9 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -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, } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 06d09bd350a..c6c6a0e4700 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -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(..) | diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 307897c4eb4..27cc5faaf20 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -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) } } diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index ca0e5dad65b..cbb6f7bce50 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -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 => { diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 7eb73a87532..07fd966f570 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -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); diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index e8885626151..1de6749200f 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -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, })) } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 587cc27f4b8..6f4480bf6dd 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -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] diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index dfcc68bf390..9e8352fde80 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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>; @@ -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. diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 9e4a7ed1ddc..4c3d5c8aaca 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -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)) ) diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 7404222a4bd..d9f77e8f04f 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -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. diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index f6ffb3c0135..8e3329e2720 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -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 = diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 201fc6ce7f2..3755dfd3f40 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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> { diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index bdaf3db8780..3da01764243 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -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 diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index af7830a63a7..6895d738625 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -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>) { - 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> { - 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] } } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 49440037af5..b43e2423757 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -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>, - 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(..) => { diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 47642798617..d40a68e6056 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -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 }; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index ec200241ee6..7c6c70024ce 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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> { 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 })); diff --git a/src/test/compile-fail/issue-27942.rs b/src/test/compile-fail/issue-27942.rs index 595e4bfb0d7..22e7de3838d 100644 --- a/src/test/compile-fail/issue-27942.rs +++ b/src/test/compile-fail/issue-27942.rs @@ -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; //~^ 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); diff --git a/src/test/compile-fail/issue-37884.rs b/src/test/compile-fail/issue-37884.rs index 28ce79ab5aa..6313293bf2b 100644 --- a/src/test/compile-fail/issue-37884.rs +++ b/src/test/compile-fail/issue-37884.rs @@ -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 //~^ 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) } From da8b6e276e6894c3926610c1350e0d62ca83fdc7 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 May 2017 15:15:36 +0300 Subject: [PATCH 08/10] rustc: remove redundant fn_id's from CodeExtentData. --- src/librustc/ich/impls_ty.rs | 5 ++--- src/librustc/infer/error_reporting/mod.rs | 4 ++-- src/librustc/middle/region.rs | 26 +++++++++-------------- src/librustc/ty/context.rs | 12 ++++------- src/librustc_mir/build/scope.rs | 2 +- 5 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index f9a86c2f010..6d6520adc4e 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -441,9 +441,8 @@ impl<'a, 'tcx> HashStable> for ::middle::region:: CodeExtentData::DestructionScope(node_id) => { node_id.hash_stable(hcx, hasher); } - CodeExtentData::CallSiteScope { fn_id, body_id } | - CodeExtentData::ParameterScope { fn_id, body_id } => { - fn_id.hash_stable(hcx, hasher); + CodeExtentData::CallSiteScope(body_id) | + CodeExtentData::ParameterScope(body_id) => { body_id.hash_stable(hcx, hasher); } CodeExtentData::Remainder(block_remainder) => { diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index da5ff6ff38a..009dfbd5402 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -153,10 +153,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }; let scope_decorated_tag = match *scope { region::CodeExtentData::Misc(_) => tag, - region::CodeExtentData::CallSiteScope { .. } => { + region::CodeExtentData::CallSiteScope(_) => { "scope of call-site for function" } - region::CodeExtentData::ParameterScope { .. } => { + region::CodeExtentData::ParameterScope(_) => { "scope of function body" } region::CodeExtentData::DestructionScope(_) => { diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 917b21c865a..2940d250dd3 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -107,11 +107,11 @@ pub enum CodeExtentData { // extent of the call-site for a function or closure (outlives // the parameters as well as the body). - CallSiteScope { fn_id: ast::NodeId, body_id: ast::NodeId }, + CallSiteScope(hir::BodyId), // extent of parameters passed to a function or closure (they // outlive its body) - ParameterScope { fn_id: ast::NodeId, body_id: ast::NodeId }, + ParameterScope(hir::BodyId), // extent of destructors for temporaries of node-id DestructionScope(ast::NodeId), @@ -157,8 +157,8 @@ impl CodeExtentData { // precise extent denoted by `self`. CodeExtentData::Remainder(br) => br.block, CodeExtentData::DestructionScope(node_id) => node_id, - CodeExtentData::CallSiteScope { fn_id: _, body_id } | - CodeExtentData::ParameterScope { fn_id: _, body_id } => body_id, + CodeExtentData::CallSiteScope(body_id) | + CodeExtentData::ParameterScope(body_id) => body_id.node_id, } } @@ -169,8 +169,8 @@ impl CodeExtentData { match hir_map.find(self.node_id()) { Some(hir_map::NodeBlock(ref blk)) => { match *self { - CodeExtentData::CallSiteScope { .. } | - CodeExtentData::ParameterScope { .. } | + CodeExtentData::CallSiteScope(_) | + CodeExtentData::ParameterScope(_) | CodeExtentData::Misc(_) | CodeExtentData::DestructionScope(_) => Some(blk.span), @@ -627,10 +627,7 @@ impl<'tcx> RegionMaps<'tcx> { self.root_body.unwrap() }); - tcx.intern_code_extent(CodeExtentData::CallSiteScope { - fn_id: tcx.hir.body_owner(body_id), - body_id: body_id.node_id - }) + tcx.intern_code_extent(CodeExtentData::CallSiteScope(body_id)) } /// Assuming that the provided region was defined within this `RegionMaps`, @@ -651,10 +648,7 @@ impl<'tcx> RegionMaps<'tcx> { let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap(); 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), - body_id: body_id.node_id - }) + tcx.intern_code_extent(CodeExtentData::CallSiteScope(body_id)) } } @@ -1172,9 +1166,9 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> { self.cx.root_id = Some(body_id.node_id); self.cx.parent = Some(self.new_code_extent( - CodeExtentData::CallSiteScope { fn_id: owner_id, body_id: body_id.node_id })); + CodeExtentData::CallSiteScope(body_id))); self.cx.parent = Some(self.new_code_extent( - CodeExtentData::ParameterScope { fn_id: owner_id, body_id: body_id.node_id })); + CodeExtentData::ParameterScope(body_id))); // The arguments and `self` are parented to the fn. self.cx.var_parent = self.cx.parent.take(); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index d69a9b3a8ce..39ab2abcc0e 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -656,17 +656,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn call_site_extent(self, fn_id: ast::NodeId) -> CodeExtent<'gcx> { - self.intern_code_extent(CodeExtentData::CallSiteScope { - fn_id, - body_id: self.hir.body_owned_by(fn_id).node_id - }) + self.intern_code_extent(CodeExtentData::CallSiteScope( + self.hir.body_owned_by(fn_id))) } pub fn parameter_extent(self, fn_id: ast::NodeId) -> CodeExtent<'gcx> { - self.intern_code_extent(CodeExtentData::ParameterScope { - fn_id, - body_id: self.hir.body_owned_by(fn_id).node_id - }) + self.intern_code_extent(CodeExtentData::ParameterScope( + self.hir.body_owned_by(fn_id))) } pub fn intern_code_extent(self, data: CodeExtentData) -> CodeExtent<'gcx> { diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 6043a696183..56ce4727d5f 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -416,7 +416,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // We want `scopes[1]`, which is the `ParameterScope`. assert!(self.scopes.len() >= 2); assert!(match *self.scopes[1].extent { - CodeExtentData::ParameterScope { .. } => true, + CodeExtentData::ParameterScope(_) => true, _ => false, }); self.scopes[1].extent From ea1c6df81eecad62ca25191042b7871291162933 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 May 2017 16:10:47 +0300 Subject: [PATCH 09/10] rustc: stop interning CodeExtent, it's small enough. --- src/librustc/cfg/construct.rs | 5 +- src/librustc/ich/impls_ty.rs | 16 +- src/librustc/infer/error_reporting/mod.rs | 12 +- src/librustc/infer/mod.rs | 2 +- .../infer/region_inference/graphviz.rs | 22 +- src/librustc/middle/expr_use_visitor.rs | 4 +- src/librustc/middle/free_region.rs | 4 +- src/librustc/middle/mem_categorization.rs | 8 +- src/librustc/middle/region.rs | 232 ++++++++---------- src/librustc/ty/context.rs | 38 +-- src/librustc/ty/fold.rs | 2 +- src/librustc/ty/maps.rs | 2 +- src/librustc/ty/mod.rs | 3 +- src/librustc/ty/sty.rs | 10 +- src/librustc/util/ppaux.rs | 4 +- src/librustc_borrowck/borrowck/check_loans.rs | 8 +- .../borrowck/gather_loans/lifetime.rs | 4 +- .../borrowck/gather_loans/mod.rs | 16 +- src/librustc_borrowck/borrowck/mod.rs | 10 +- src/librustc_const_eval/check_match.rs | 2 +- src/librustc_driver/test.rs | 11 +- src/librustc_metadata/decoder.rs | 7 - src/librustc_mir/build/expr/as_operand.rs | 4 +- src/librustc_mir/build/expr/as_rvalue.rs | 4 +- src/librustc_mir/build/expr/as_temp.rs | 4 +- src/librustc_mir/build/mod.rs | 6 +- src/librustc_mir/build/scope.rs | 30 +-- src/librustc_mir/hair/cx/block.rs | 14 +- src/librustc_mir/hair/cx/expr.rs | 22 +- src/librustc_mir/hair/cx/mod.rs | 2 +- src/librustc_mir/hair/mod.rs | 18 +- src/librustc_typeck/check/dropck.rs | 2 +- src/librustc_typeck/check/mod.rs | 9 +- src/librustc_typeck/check/regionck.rs | 20 +- src/librustdoc/clean/mod.rs | 2 +- 35 files changed, 239 insertions(+), 320 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index a8ad49c6582..c1c195852f9 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -10,6 +10,7 @@ use rustc_data_structures::graph; use cfg::*; +use middle::region::CodeExtent; use ty::{self, TyCtxt}; use syntax::ast; use syntax::ptr::P; @@ -586,8 +587,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { scope_id: ast::NodeId, to_index: CFGIndex) { let mut data = CFGEdgeData { exiting_scopes: vec![] }; - let mut scope = self.tcx.node_extent(from_expr.id); - let target_scope = self.tcx.node_extent(scope_id); + let mut scope = CodeExtent::Misc(from_expr.id); + let target_scope = CodeExtent::Misc(scope_id); let region_maps = self.tcx.region_maps(self.owner_def_id); while scope != target_scope { data.exiting_scopes.push(scope.node_id()); diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 6d6520adc4e..3bbac8d6a64 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -39,7 +39,7 @@ impl<'a, 'tcx> HashStable> for ty::subst::Kind<'t } } -impl<'a, 'tcx> HashStable> for ty::RegionKind<'tcx> { +impl<'a, 'tcx> HashStable> for ty::RegionKind { fn hash_stable(&self, hcx: &mut StableHashingContext<'a, 'tcx>, hasher: &mut StableHasher) { @@ -428,24 +428,24 @@ impl_stable_hash_for!(enum ty::cast::CastKind { FnPtrAddrCast }); -impl<'a, 'tcx> HashStable> for ::middle::region::CodeExtentData +impl<'a, 'tcx> HashStable> for ::middle::region::CodeExtent { fn hash_stable(&self, hcx: &mut StableHashingContext<'a, 'tcx>, hasher: &mut StableHasher) { - use middle::region::CodeExtentData; + use middle::region::CodeExtent; mem::discriminant(self).hash_stable(hcx, hasher); match *self { - CodeExtentData::Misc(node_id) | - CodeExtentData::DestructionScope(node_id) => { + CodeExtent::Misc(node_id) | + CodeExtent::DestructionScope(node_id) => { node_id.hash_stable(hcx, hasher); } - CodeExtentData::CallSiteScope(body_id) | - CodeExtentData::ParameterScope(body_id) => { + CodeExtent::CallSiteScope(body_id) | + CodeExtent::ParameterScope(body_id) => { body_id.hash_stable(hcx, hasher); } - CodeExtentData::Remainder(block_remainder) => { + CodeExtent::Remainder(block_remainder) => { block_remainder.hash_stable(hcx, hasher); } } diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 009dfbd5402..c07b3b3c4be 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -151,19 +151,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { return; } }; - let scope_decorated_tag = match *scope { - region::CodeExtentData::Misc(_) => tag, - region::CodeExtentData::CallSiteScope(_) => { + let scope_decorated_tag = match scope { + region::CodeExtent::Misc(_) => tag, + region::CodeExtent::CallSiteScope(_) => { "scope of call-site for function" } - region::CodeExtentData::ParameterScope(_) => { + region::CodeExtent::ParameterScope(_) => { "scope of function body" } - region::CodeExtentData::DestructionScope(_) => { + region::CodeExtent::DestructionScope(_) => { new_string = format!("destruction scope surrounding {}", tag); &new_string[..] } - region::CodeExtentData::Remainder(r) => { + region::CodeExtent::Remainder(r) => { new_string = format!("block suffix following statement {}", r.first_statement_index); &new_string[..] diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index e42280124a1..1ecc277c7ca 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1324,7 +1324,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn resolve_regions_and_report_errors(&self, region_context: DefId, - region_map: &RegionMaps<'tcx>, + region_map: &RegionMaps, free_regions: &FreeRegionMap<'tcx>) { let region_rels = RegionRelations::new(self.tcx, region_context, diff --git a/src/librustc/infer/region_inference/graphviz.rs b/src/librustc/infer/region_inference/graphviz.rs index c48b8f610a2..cce253c1a1a 100644 --- a/src/librustc/infer/region_inference/graphviz.rs +++ b/src/librustc/infer/region_inference/graphviz.rs @@ -124,20 +124,20 @@ struct ConstraintGraph<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { graph_name: String, region_rels: &'a RegionRelations<'a, 'gcx, 'tcx>, map: &'a FxHashMap, SubregionOrigin<'tcx>>, - node_ids: FxHashMap, usize>, + node_ids: FxHashMap, } #[derive(Clone, Hash, PartialEq, Eq, Debug, Copy)] -enum Node<'tcx> { +enum Node { RegionVid(ty::RegionVid), - Region(ty::RegionKind<'tcx>), + Region(ty::RegionKind), } // type Edge = Constraint; #[derive(Clone, PartialEq, Eq, Debug, Copy)] enum Edge<'tcx> { Constraint(Constraint<'tcx>), - EnclScope(CodeExtent<'tcx>, CodeExtent<'tcx>), + EnclScope(CodeExtent, CodeExtent), } impl<'a, 'gcx, 'tcx> ConstraintGraph<'a, 'gcx, 'tcx> { @@ -176,7 +176,7 @@ impl<'a, 'gcx, 'tcx> ConstraintGraph<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'gcx, 'tcx> { - type Node = Node<'tcx>; + type Node = Node; type Edge = Edge<'tcx>; fn graph_id(&self) -> dot::Id { dot::Id::new(&*self.graph_name).unwrap() @@ -209,7 +209,7 @@ impl<'a, 'gcx, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'gcx, 'tcx> { } } -fn constraint_to_nodes<'tcx>(c: &Constraint<'tcx>) -> (Node<'tcx>, Node<'tcx>) { +fn constraint_to_nodes(c: &Constraint) -> (Node, Node) { match *c { Constraint::ConstrainVarSubVar(rv_1, rv_2) => (Node::RegionVid(rv_1), Node::RegionVid(rv_2)), @@ -222,7 +222,7 @@ fn constraint_to_nodes<'tcx>(c: &Constraint<'tcx>) -> (Node<'tcx>, Node<'tcx>) { } } -fn edge_to_nodes<'tcx>(e: &Edge<'tcx>) -> (Node<'tcx>, Node<'tcx>) { +fn edge_to_nodes(e: &Edge) -> (Node, Node) { match *e { Edge::Constraint(ref c) => constraint_to_nodes(c), Edge::EnclScope(sub, sup) => { @@ -233,9 +233,9 @@ fn edge_to_nodes<'tcx>(e: &Edge<'tcx>) -> (Node<'tcx>, Node<'tcx>) { } impl<'a, 'gcx, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'gcx, 'tcx> { - type Node = Node<'tcx>; + type Node = Node; type Edge = Edge<'tcx>; - fn nodes(&self) -> dot::Nodes> { + fn nodes(&self) -> dot::Nodes { let mut set = FxHashSet(); for node in self.node_ids.keys() { set.insert(*node); @@ -250,12 +250,12 @@ impl<'a, 'gcx, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'gcx, 'tcx> { debug!("region graph has {} edges", v.len()); Cow::Owned(v) } - fn source(&self, edge: &Edge<'tcx>) -> Node<'tcx> { + fn source(&self, edge: &Edge<'tcx>) -> Node { let (n1, _) = edge_to_nodes(edge); debug!("edge {:?} has source {:?}", edge, n1); n1 } - fn target(&self, edge: &Edge<'tcx>) -> Node<'tcx> { + fn target(&self, edge: &Edge<'tcx>) -> Node { let (_, n2) = edge_to_nodes(edge); debug!("edge {:?} has target {:?}", edge, n2); n2 diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 41f9311dd80..99b140f690a 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -271,7 +271,7 @@ enum PassArgs { impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { pub fn new(delegate: &'a mut (Delegate<'tcx>+'a), - region_maps: &'a RegionMaps<'tcx>, + region_maps: &'a RegionMaps, infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self { @@ -283,7 +283,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a), infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - region_maps: &'a RegionMaps<'tcx>, + region_maps: &'a RegionMaps, options: mc::MemCategorizationOptions) -> Self { diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs index 8168837b1f5..6a21bdc19e0 100644 --- a/src/librustc/middle/free_region.rs +++ b/src/librustc/middle/free_region.rs @@ -35,7 +35,7 @@ pub struct RegionRelations<'a, 'gcx: 'tcx, 'tcx: 'a> { pub context: DefId, /// region maps for the given context - pub region_maps: &'a RegionMaps<'tcx>, + pub region_maps: &'a RegionMaps, /// free-region relationships pub free_regions: &'a FreeRegionMap<'tcx>, @@ -45,7 +45,7 @@ impl<'a, 'gcx, 'tcx> RegionRelations<'a, 'gcx, 'tcx> { pub fn new( tcx: TyCtxt<'a, 'gcx, 'tcx>, context: DefId, - region_maps: &'a RegionMaps<'tcx>, + region_maps: &'a RegionMaps, free_regions: &'a FreeRegionMap<'tcx>, ) -> Self { Self { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 8e25c6facf2..d0adf51d79e 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -290,7 +290,7 @@ impl ast_node for hir::Pat { #[derive(Clone)] pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - pub region_maps: &'a RegionMaps<'tcx>, + pub region_maps: &'a RegionMaps, options: MemCategorizationOptions, } @@ -406,7 +406,7 @@ impl MutabilityCategory { impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { /// Context should be the `DefId` we use to fetch region-maps. pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - region_maps: &'a RegionMaps<'tcx>) + region_maps: &'a RegionMaps) -> MemCategorizationContext<'a, 'gcx, 'tcx> { MemCategorizationContext::with_options(infcx, region_maps, @@ -414,7 +414,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } pub fn with_options(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - region_maps: &'a RegionMaps<'tcx>, + region_maps: &'a RegionMaps, options: MemCategorizationOptions) -> MemCategorizationContext<'a, 'gcx, 'tcx> { MemCategorizationContext { @@ -839,7 +839,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { pub fn temporary_scope(&self, id: ast::NodeId) -> (ty::Region<'tcx>, ty::Region<'tcx>) { let (scope, old_scope) = - self.region_maps.old_and_new_temporary_scope(self.tcx(), id); + self.region_maps.old_and_new_temporary_scope(id); (self.tcx().mk_region(match scope { Some(scope) => ty::ReScope(scope), None => ty::ReStatic diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 2940d250dd3..331683381a4 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -22,7 +22,6 @@ use ty; use std::mem; use std::rc::Rc; -use serialize; use syntax::codemap; use syntax::ast; use syntax_pos::Span; @@ -35,11 +34,6 @@ use hir::intravisit::{self, Visitor, NestedVisitorMap}; use hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local}; use mir::transform::MirSource; -pub type CodeExtent<'tcx> = &'tcx CodeExtentData; - -impl<'tcx> serialize::UseSpecializedEncodable for CodeExtent<'tcx> {} -impl<'tcx> serialize::UseSpecializedDecodable for CodeExtent<'tcx> {} - /// CodeExtent represents a statically-describable extent that can be /// used to bound the lifetime/region for values. /// @@ -102,7 +96,7 @@ impl<'tcx> serialize::UseSpecializedDecodable for CodeExtent<'tcx> {} /// actually attach a more meaningful ordering to scopes than the one /// generated via deriving here. #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)] -pub enum CodeExtentData { +pub enum CodeExtent { Misc(ast::NodeId), // extent of the call-site for a function or closure (outlives @@ -131,9 +125,9 @@ pub enum CodeExtentData { /// * the subscope with `first_statement_index == 0` is scope of both /// `a` and `b`; it does not include EXPR_1, but does include /// everything after that first `let`. (If you want a scope that -/// includes EXPR_1 as well, then do not use `CodeExtentData::Remainder`, +/// includes EXPR_1 as well, then do not use `CodeExtent::Remainder`, /// but instead another `CodeExtent` that encompasses the whole block, -/// e.g. `CodeExtentData::Misc`. +/// e.g. `CodeExtent::Misc`. /// /// * the subscope with `first_statement_index == 1` is scope of `c`, /// and thus does not include EXPR_2, but covers the `...`. @@ -144,21 +138,21 @@ pub struct BlockRemainder { pub first_statement_index: u32, } -impl CodeExtentData { +impl CodeExtent { /// Returns a node id associated with this scope. /// /// NB: likely to be replaced as API is refined; e.g. pnkfelix /// anticipates `fn entry_node_id` and `fn each_exit_node_id`. pub fn node_id(&self) -> ast::NodeId { match *self { - CodeExtentData::Misc(node_id) => node_id, + CodeExtent::Misc(node_id) => node_id, // These cases all return rough approximations to the // precise extent denoted by `self`. - CodeExtentData::Remainder(br) => br.block, - CodeExtentData::DestructionScope(node_id) => node_id, - CodeExtentData::CallSiteScope(body_id) | - CodeExtentData::ParameterScope(body_id) => body_id.node_id, + CodeExtent::Remainder(br) => br.block, + CodeExtent::DestructionScope(node_id) => node_id, + CodeExtent::CallSiteScope(body_id) | + CodeExtent::ParameterScope(body_id) => body_id.node_id, } } @@ -169,12 +163,12 @@ impl CodeExtentData { match hir_map.find(self.node_id()) { Some(hir_map::NodeBlock(ref blk)) => { match *self { - CodeExtentData::CallSiteScope(_) | - CodeExtentData::ParameterScope(_) | - CodeExtentData::Misc(_) | - CodeExtentData::DestructionScope(_) => Some(blk.span), + CodeExtent::CallSiteScope(_) | + CodeExtent::ParameterScope(_) | + CodeExtent::Misc(_) | + CodeExtent::DestructionScope(_) => Some(blk.span), - CodeExtentData::Remainder(r) => { + CodeExtent::Remainder(r) => { assert_eq!(r.block, blk.id); // Want span for extent starting after the // indexed statement and ending at end of @@ -197,7 +191,7 @@ impl CodeExtentData { } /// The region maps encode information about region relationships. -pub struct RegionMaps<'tcx> { +pub struct RegionMaps { /// If not empty, this body is the root of this region hierarchy. root_body: Option, @@ -212,14 +206,14 @@ pub struct RegionMaps<'tcx> { /// conditional expression or repeating block. (Note that the /// enclosing scope id for the block associated with a closure is /// the closure itself.) - scope_map: FxHashMap, CodeExtent<'tcx>>, + scope_map: FxHashMap, /// `var_map` maps from a variable or binding id to the block in /// which that variable is declared. - var_map: NodeMap>, + var_map: NodeMap, /// maps from a node-id to the associated destruction scope (if any) - destruction_scopes: NodeMap>, + destruction_scopes: NodeMap, /// `rvalue_scopes` includes entries for those expressions whose cleanup scope is /// larger than the default. The map goes from the expression id @@ -227,14 +221,14 @@ pub struct RegionMaps<'tcx> { /// table, the appropriate cleanup scope is the innermost /// enclosing statement, conditional expression, or repeating /// block (see `terminating_scopes`). - rvalue_scopes: NodeMap>, + rvalue_scopes: NodeMap, /// Records the value of rvalue scopes before they were shrunk by /// #36082, for error reporting. /// /// FIXME: this should be temporary. Remove this by 1.18.0 or /// so. - shrunk_rvalue_scopes: NodeMap>, + shrunk_rvalue_scopes: NodeMap, /// Encodes the hierarchy of fn bodies. Every fn body (including /// closures) forms its own distinct region hierarchy, rooted in @@ -250,7 +244,7 @@ pub struct RegionMaps<'tcx> { } #[derive(Debug, Copy, Clone)] -pub struct Context<'tcx> { +pub struct Context { /// the root of the current region tree. This is typically the id /// of the innermost fn body. Each fn forms its own disjoint tree /// in the region hierarchy. These fn bodies are themselves @@ -260,19 +254,19 @@ pub struct Context<'tcx> { root_id: Option, /// the scope that contains any new variables declared - var_parent: Option>, + var_parent: Option, /// region parent of expressions etc - parent: Option>, + parent: Option, } struct RegionResolutionVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, // Generated maps: - region_maps: &'a mut RegionMaps<'tcx>, + region_maps: &'a mut RegionMaps, - cx: Context<'tcx>, + cx: Context, map: &'a hir_map::Map<'tcx>, @@ -300,7 +294,7 @@ struct RegionResolutionVisitor<'a, 'tcx: 'a> { } -impl<'tcx> RegionMaps<'tcx> { +impl<'tcx> RegionMaps { pub fn new() -> Self { RegionMaps { root_body: None, @@ -315,8 +309,8 @@ impl<'tcx> RegionMaps<'tcx> { } pub fn record_code_extent(&mut self, - child: CodeExtent<'tcx>, - parent: Option>) { + child: CodeExtent, + parent: Option) { debug!("{:?}.parent = {:?}", child, parent); if let Some(p) = parent { @@ -325,24 +319,24 @@ impl<'tcx> RegionMaps<'tcx> { } // record the destruction scopes for later so we can query them - if let &CodeExtentData::DestructionScope(n) = child { + if let CodeExtent::DestructionScope(n) = child { self.destruction_scopes.insert(n, child); } } - pub fn each_encl_scope(&self, mut e:E) where E: FnMut(CodeExtent<'tcx>, CodeExtent<'tcx>) { + pub fn each_encl_scope(&self, mut e:E) where E: FnMut(CodeExtent, CodeExtent) { for (&child, &parent) in &self.scope_map { e(child, parent) } } - pub fn each_var_scope(&self, mut e:E) where E: FnMut(&ast::NodeId, CodeExtent<'tcx>) { - for (child, parent) in self.var_map.iter() { + pub fn each_var_scope(&self, mut e:E) where E: FnMut(&ast::NodeId, CodeExtent) { + for (child, &parent) in self.var_map.iter() { e(child, parent) } } - pub fn opt_destruction_extent(&self, n: ast::NodeId) -> Option> { + pub fn opt_destruction_extent(&self, n: ast::NodeId) -> Option { self.destruction_scopes.get(&n).cloned() } @@ -366,48 +360,46 @@ impl<'tcx> RegionMaps<'tcx> { } } - fn record_var_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent<'tcx>) { + fn record_var_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent) { debug!("record_var_scope(sub={:?}, sup={:?})", var, lifetime); assert!(var != lifetime.node_id()); self.var_map.insert(var, lifetime); } - fn record_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent<'tcx>) { + fn record_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent) { debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime); assert!(var != lifetime.node_id()); self.rvalue_scopes.insert(var, lifetime); } - fn record_shrunk_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent<'tcx>) { + fn record_shrunk_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent) { debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime); assert!(var != lifetime.node_id()); self.shrunk_rvalue_scopes.insert(var, lifetime); } - pub fn opt_encl_scope(&self, id: CodeExtent<'tcx>) -> Option> { + pub fn opt_encl_scope(&self, id: CodeExtent) -> Option { //! Returns the narrowest scope that encloses `id`, if any. self.scope_map.get(&id).cloned() } #[allow(dead_code)] // used in cfg - pub fn encl_scope(&self, id: CodeExtent<'tcx>) -> CodeExtent<'tcx> { + pub fn encl_scope(&self, id: CodeExtent) -> CodeExtent { //! Returns the narrowest scope that encloses `id`, if any. self.opt_encl_scope(id).unwrap() } /// Returns the lifetime of the local variable `var_id` - pub fn var_scope(&self, var_id: ast::NodeId) -> CodeExtent<'tcx> { + pub fn var_scope(&self, var_id: ast::NodeId) -> CodeExtent { match self.var_map.get(&var_id) { Some(&r) => r, None => { bug!("no enclosing scope for id {:?}", var_id); } } } - pub fn temporary_scope2<'a, 'gcx: 'tcx>(&self, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - expr_id: ast::NodeId) - -> (Option>, bool) { - let temporary_scope = self.temporary_scope(tcx, expr_id); + pub fn temporary_scope2(&self, expr_id: ast::NodeId) + -> (Option, bool) { + let temporary_scope = self.temporary_scope(expr_id); let was_shrunk = match self.shrunk_rvalue_scopes.get(&expr_id) { Some(&s) => { info!("temporary_scope2({:?}, scope={:?}, shrunk={:?})", @@ -420,23 +412,18 @@ impl<'tcx> RegionMaps<'tcx> { (temporary_scope, was_shrunk) } - pub fn old_and_new_temporary_scope<'a, 'gcx: 'tcx>(&self, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - expr_id: ast::NodeId) - -> (Option>, - Option>) + pub fn old_and_new_temporary_scope(&self, expr_id: ast::NodeId) + -> (Option, + Option) { - let temporary_scope = self.temporary_scope(tcx, expr_id); + let temporary_scope = self.temporary_scope(expr_id); (temporary_scope, self.shrunk_rvalue_scopes .get(&expr_id).cloned() .or(temporary_scope)) } - pub fn temporary_scope<'a, 'gcx: 'tcx>(&self, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - expr_id: ast::NodeId) - -> Option> { + pub fn temporary_scope(&self, expr_id: ast::NodeId) -> Option { //! Returns the scope when temp created by expr_id will be cleaned up // check for a designated rvalue scope @@ -449,11 +436,11 @@ impl<'tcx> RegionMaps<'tcx> { // if there's one. Static items, for instance, won't // have an enclosing scope, hence no scope will be // returned. - let mut id = tcx.node_extent(expr_id); + let mut id = CodeExtent::Misc(expr_id); - while let Some(&p) = self.scope_map.get(id) { - match *p { - CodeExtentData::DestructionScope(..) => { + while let Some(&p) = self.scope_map.get(&id) { + match p { + CodeExtent::DestructionScope(..) => { debug!("temporary_scope({:?}) = {:?} [enclosing]", expr_id, id); return Some(id); @@ -466,7 +453,7 @@ impl<'tcx> RegionMaps<'tcx> { return None; } - pub fn var_region(&self, id: ast::NodeId) -> ty::RegionKind<'tcx> { + pub fn var_region(&self, id: ast::NodeId) -> ty::RegionKind { //! Returns the lifetime of the variable `id`. let scope = ty::ReScope(self.var_scope(id)); @@ -508,9 +495,9 @@ impl<'tcx> RegionMaps<'tcx> { /// Finds the nearest common ancestor (if any) of two scopes. That is, finds the smallest /// scope which is greater than or equal to both `scope_a` and `scope_b`. pub fn nearest_common_ancestor(&self, - scope_a: CodeExtent<'tcx>, - scope_b: CodeExtent<'tcx>) - -> CodeExtent<'tcx> { + scope_a: CodeExtent, + scope_b: CodeExtent) + -> CodeExtent { if scope_a == scope_b { return scope_a; } /// [1] The initial values for `a_buf` and `b_buf` are not used. @@ -518,9 +505,9 @@ impl<'tcx> RegionMaps<'tcx> { /// is re-initialized with new values (or else fallback to a /// heap-allocated vector). let mut a_buf: [CodeExtent; 32] = [scope_a /* [1] */; 32]; - let mut a_vec: Vec> = vec![]; + let mut a_vec: Vec = vec![]; let mut b_buf: [CodeExtent; 32] = [scope_b /* [1] */; 32]; - let mut b_vec: Vec> = vec![]; + let mut b_vec: Vec = vec![]; let scope_map = &self.scope_map; let a_ancestors = ancestors_of(scope_map, scope_a, &mut a_buf, &mut a_vec); let b_ancestors = ancestors_of(scope_map, scope_b, &mut b_buf, &mut b_vec); @@ -544,8 +531,8 @@ impl<'tcx> RegionMaps<'tcx> { let a_root_scope = a_ancestors[a_index]; let b_root_scope = a_ancestors[a_index]; return match (a_root_scope, b_root_scope) { - (&CodeExtentData::DestructionScope(a_root_id), - &CodeExtentData::DestructionScope(b_root_id)) => { + (CodeExtent::DestructionScope(a_root_id), + CodeExtent::DestructionScope(b_root_id)) => { if self.fn_is_enclosed_by(a_root_id, b_root_id) { // `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a` scope_b @@ -576,11 +563,11 @@ impl<'tcx> RegionMaps<'tcx> { } } - fn ancestors_of<'a, 'tcx>(scope_map: &FxHashMap, CodeExtent<'tcx>>, - scope: CodeExtent<'tcx>, - buf: &'a mut [CodeExtent<'tcx>; 32], - vec: &'a mut Vec>) - -> &'a [CodeExtent<'tcx>] { + fn ancestors_of<'a, 'tcx>(scope_map: &FxHashMap, + scope: CodeExtent, + buf: &'a mut [CodeExtent; 32], + vec: &'a mut Vec) + -> &'a [CodeExtent] { // debug!("ancestors_of(scope={:?})", scope); let mut scope = scope; @@ -588,7 +575,7 @@ impl<'tcx> RegionMaps<'tcx> { while i < 32 { buf[i] = scope; match scope_map.get(&scope) { - Some(superscope) => scope = superscope, + Some(&superscope) => scope = superscope, _ => return &buf[..i+1] } i += 1; @@ -599,7 +586,7 @@ impl<'tcx> RegionMaps<'tcx> { loop { vec.push(scope); match scope_map.get(&scope) { - Some(superscope) => scope = superscope, + Some(&superscope) => scope = superscope, _ => return &*vec } } @@ -610,7 +597,7 @@ impl<'tcx> RegionMaps<'tcx> { /// 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> { + -> CodeExtent { let param_owner = tcx.parent_def_id(br.def_id).unwrap(); let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap(); @@ -627,13 +614,13 @@ impl<'tcx> RegionMaps<'tcx> { self.root_body.unwrap() }); - tcx.intern_code_extent(CodeExtentData::CallSiteScope(body_id)) + CodeExtent::CallSiteScope(body_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) - -> CodeExtent<'tcx> { + -> CodeExtent { let param_owner = match fr.bound_region { ty::BoundRegion::BrNamed(def_id, _) => { tcx.parent_def_id(def_id).unwrap() @@ -646,9 +633,7 @@ impl<'tcx> RegionMaps<'tcx> { assert_eq!(param_owner, fr.scope); let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap(); - let body_id = tcx.hir.body_owned_by(param_owner_id); - - tcx.intern_code_extent(CodeExtentData::CallSiteScope(body_id)) + CodeExtent::CallSiteScope(tcx.hir.body_owned_by(param_owner_id)) } } @@ -671,7 +656,6 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk: debug!("resolve_block(blk.id={:?})", blk.id); let prev_cx = visitor.cx; - let block_extent = visitor.new_node_extent_with_dtor(blk.id); // We treat the tail expression in the block (if any) somewhat // differently from the statements. The issue has to do with @@ -698,11 +682,8 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk: // `other_argument()` has run and also the call to `quux(..)` // itself has returned. - visitor.cx = Context { - root_id: prev_cx.root_id, - var_parent: Some(block_extent), - parent: Some(block_extent), - }; + visitor.enter_node_extent_with_dtor(blk.id); + visitor.cx.var_parent = visitor.cx.parent; { // This block should be kept approximately in sync with @@ -718,17 +699,13 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk: // has the previous subscope in the block as a parent, // except for the first such subscope, which has the // block itself as a parent. - let stmt_extent = visitor.new_code_extent( - CodeExtentData::Remainder(BlockRemainder { + visitor.enter_code_extent( + CodeExtent::Remainder(BlockRemainder { block: blk.id, first_statement_index: i as u32 }) ); - visitor.cx = Context { - root_id: prev_cx.root_id, - var_parent: Some(stmt_extent), - parent: Some(stmt_extent), - }; + visitor.cx.var_parent = visitor.cx.parent; } visitor.visit_stmt(statement) } @@ -749,7 +726,7 @@ fn resolve_arm<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, arm: & } fn resolve_pat<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, pat: &'tcx hir::Pat) { - visitor.new_node_extent(pat.id); + visitor.record_code_extent(CodeExtent::Misc(pat.id)); // If this is a binding then record the lifetime of that binding. if let PatKind::Binding(..) = pat.node { @@ -769,20 +746,20 @@ fn resolve_stmt<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, stmt: // statement plus its destructors, and thus the extent for which // regions referenced by the destructors need to survive. visitor.terminating_scopes.insert(stmt_id); - let stmt_extent = visitor.new_node_extent_with_dtor(stmt_id); let prev_parent = visitor.cx.parent; - visitor.cx.parent = Some(stmt_extent); + visitor.enter_node_extent_with_dtor(stmt_id); + intravisit::walk_stmt(visitor, stmt); + visitor.cx.parent = prev_parent; } fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: &'tcx hir::Expr) { debug!("resolve_expr(expr.id={:?})", expr.id); - let expr_extent = visitor.new_node_extent_with_dtor(expr.id); let prev_cx = visitor.cx; - visitor.cx.parent = Some(expr_extent); + visitor.enter_node_extent_with_dtor(expr.id); { let terminating_scopes = &mut visitor.terminating_scopes; @@ -822,7 +799,7 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: } hir::ExprMatch(..) => { - visitor.cx.var_parent = Some(expr_extent); + visitor.cx.var_parent = visitor.cx.parent; } hir::ExprAssignOp(..) | hir::ExprIndex(..) | @@ -1009,7 +986,7 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, fn record_rvalue_scope_if_borrow_expr<'a, 'tcx>( visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: &hir::Expr, - blk_id: CodeExtent<'tcx>) + blk_id: CodeExtent) { match expr.node { hir::ExprAddrOf(_, ref subexpr) => { @@ -1059,7 +1036,7 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, /// Note: ET is intended to match "rvalues or lvalues based on rvalues". fn record_rvalue_scope<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: &hir::Expr, - blk_scope: CodeExtent<'tcx>, + blk_scope: CodeExtent, is_shrunk: bool) { let mut expr = expr; loop { @@ -1092,43 +1069,28 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, } impl<'a, 'tcx> RegionResolutionVisitor<'a, 'tcx> { - pub fn intern_code_extent(&mut self, - data: CodeExtentData, - parent: Option>) - -> CodeExtent<'tcx> { - let code_extent = self.tcx.intern_code_extent(data); - self.region_maps.record_code_extent(code_extent, parent); - code_extent - } - - pub fn intern_node(&mut self, - n: ast::NodeId, - parent: Option>) -> CodeExtent<'tcx> { - self.intern_code_extent(CodeExtentData::Misc(n), parent) - } - /// Records the current parent (if any) as the parent of `child_scope`. - fn new_code_extent(&mut self, child_scope: CodeExtentData) -> CodeExtent<'tcx> { + fn record_code_extent(&mut self, child_scope: CodeExtent) { let parent = self.cx.parent; - self.intern_code_extent(child_scope, parent) + self.region_maps.record_code_extent(child_scope, parent); } - fn new_node_extent(&mut self, child_scope: ast::NodeId) -> CodeExtent<'tcx> { - self.new_code_extent(CodeExtentData::Misc(child_scope)) + /// Records the current parent (if any) as the parent of `child_scope`, + /// and sets `child_scope` as the new current parent. + fn enter_code_extent(&mut self, child_scope: CodeExtent) { + self.record_code_extent(child_scope); + self.cx.parent = Some(child_scope); } - fn new_node_extent_with_dtor(&mut self, id: ast::NodeId) -> CodeExtent<'tcx> { + fn enter_node_extent_with_dtor(&mut self, id: ast::NodeId) { // If node was previously marked as a terminating scope during the // recursive visit of its parent node in the AST, then we need to // account for the destruction scope representing the extent of // the destructors that run immediately after it completes. if self.terminating_scopes.contains(&id) { - let ds = self.new_code_extent( - CodeExtentData::DestructionScope(id)); - self.intern_node(id, Some(ds)) - } else { - self.new_node_extent(id) + self.enter_code_extent(CodeExtent::DestructionScope(id)); } + self.enter_code_extent(CodeExtent::Misc(id)); } } @@ -1165,10 +1127,8 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> { } self.cx.root_id = Some(body_id.node_id); - self.cx.parent = Some(self.new_code_extent( - CodeExtentData::CallSiteScope(body_id))); - self.cx.parent = Some(self.new_code_extent( - CodeExtentData::ParameterScope(body_id))); + self.enter_code_extent(CodeExtent::CallSiteScope(body_id)); + self.enter_code_extent(CodeExtent::ParameterScope(body_id)); // The arguments and `self` are parented to the fn. self.cx.var_parent = self.cx.parent.take(); @@ -1203,7 +1163,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> { } fn region_maps<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Rc> + -> Rc { let closure_base_def_id = tcx.closure_base_def_id(def_id); if closure_base_def_id != def_id { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 39ab2abcc0e..b9355c264b3 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -21,7 +21,6 @@ use hir::map as hir_map; use hir::map::DisambiguatedDefPathData; use middle::free_region::FreeRegionMap; use middle::lang_items; -use middle::region::{CodeExtent, CodeExtentData}; use middle::resolve_lifetime; use middle::stability; use mir::Mir; @@ -99,7 +98,7 @@ pub struct CtxtInterners<'tcx> { type_: RefCell>>>, type_list: RefCell>>>>, substs: RefCell>>>, - region: RefCell>>>, + region: RefCell>>, existential_predicates: RefCell>>>>, predicates: RefCell>>>>, } @@ -548,8 +547,6 @@ pub struct GlobalCtxt<'tcx> { layout_interner: RefCell>, - code_extent_interner: RefCell>>, - /// A vector of every trait accessible in the whole crate /// (i.e. including those from subcrates). This is used only for /// error reporting, and so is lazily initialised and generally @@ -651,32 +648,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { interned } - pub fn node_extent(self, n: ast::NodeId) -> CodeExtent<'gcx> { - self.intern_code_extent(CodeExtentData::Misc(n)) - } - - pub fn call_site_extent(self, fn_id: ast::NodeId) -> CodeExtent<'gcx> { - self.intern_code_extent(CodeExtentData::CallSiteScope( - self.hir.body_owned_by(fn_id))) - } - - pub fn parameter_extent(self, fn_id: ast::NodeId) -> CodeExtent<'gcx> { - self.intern_code_extent(CodeExtentData::ParameterScope( - self.hir.body_owned_by(fn_id))) - } - - pub fn intern_code_extent(self, data: CodeExtentData) -> CodeExtent<'gcx> { - if let Some(st) = self.code_extent_interner.borrow().get(&data) { - return st; - } - - let interned = self.global_interners.arena.alloc(data); - if let Some(prev) = self.code_extent_interner.borrow_mut().replace(interned) { - bug!("Tried to overwrite interned code-extent: {:?}", prev) - } - interned - } - pub fn intern_layout(self, layout: Layout) -> &'gcx Layout { if let Some(layout) = self.layout_interner.borrow().get(&layout) { return layout; @@ -764,7 +735,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { data_layout: data_layout, layout_cache: RefCell::new(FxHashMap()), layout_interner: RefCell::new(FxHashSet()), - code_extent_interner: RefCell::new(FxHashSet()), layout_depth: Cell::new(0), derive_macros: RefCell::new(NodeMap()), stability_interner: RefCell::new(FxHashSet()), @@ -1106,8 +1076,8 @@ impl<'tcx: 'lcx, 'lcx> Borrow<[Kind<'lcx>]> for Interned<'tcx, Substs<'tcx>> { } } -impl<'tcx> Borrow> for Interned<'tcx, RegionKind<'tcx>> { - fn borrow<'a>(&'a self) -> &'a RegionKind<'tcx> { +impl<'tcx> Borrow for Interned<'tcx, RegionKind> { + fn borrow<'a>(&'a self) -> &'a RegionKind { &self.0 } } @@ -1206,7 +1176,7 @@ direct_interners!('tcx, &ty::ReVar(_) | &ty::ReSkolemized(..) => true, _ => false } - }) -> RegionKind<'tcx> + }) -> RegionKind ); macro_rules! slice_interners { diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 6820b9af940..6de3c018bda 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -536,7 +536,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // regions. See comment on `shift_regions_through_binders` method in // `subst.rs` for more details. -pub fn shift_region<'tcx>(region: ty::RegionKind<'tcx>, amount: u32) -> ty::RegionKind<'tcx> { +pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind { match region { ty::ReLateBound(debruijn, br) => { ty::ReLateBound(debruijn.shifted(amount), br) diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 3b5dc2ae164..1fd9e8f7375 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -801,7 +801,7 @@ define_maps! { <'tcx> /// Per-function `RegionMaps`. The `DefId` should be the owner-def-id for the fn body; /// in the case of closures or "inline" expressions, this will be redirected to the enclosing /// fn item. - [] region_maps: RegionMaps(DefId) -> Rc>, + [] region_maps: RegionMaps(DefId) -> Rc, [] mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx mir::Mir<'tcx>, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 51bd0b88bac..6ca401d27ac 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -24,6 +24,7 @@ use middle::const_val::ConstVal; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; use middle::privacy::AccessLevels; use middle::resolve_lifetime::ObjectLifetimeDefault; +use middle::region::CodeExtent; use mir::Mir; use traits; use ty; @@ -2435,7 +2436,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn node_scope_region(self, id: NodeId) -> Region<'tcx> { - self.mk_region(ty::ReScope(self.node_extent(id))) + self.mk_region(ty::ReScope(CodeExtent::Misc(id))) } /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err` diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 4faefc0fca9..cfbf1244db3 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -684,7 +684,7 @@ pub struct DebruijnIndex { pub depth: u32, } -pub type Region<'tcx> = &'tcx RegionKind<'tcx>; +pub type Region<'tcx> = &'tcx RegionKind; /// Representation of regions. /// @@ -743,7 +743,7 @@ pub type Region<'tcx> = &'tcx RegionKind<'tcx>; /// [1] http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/ /// [2] http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/ #[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable)] -pub enum RegionKind<'tcx> { +pub enum RegionKind { // Region bound in a type or fn declaration which will be // substituted 'early' -- that is, at the same time when type // parameters are substituted. @@ -761,7 +761,7 @@ pub enum RegionKind<'tcx> { /// A concrete region naming some statically determined extent /// (e.g. an expression or sequence of statements) within the /// current function. - ReScope(region::CodeExtent<'tcx>), + ReScope(region::CodeExtent), /// Static data that has an "infinite" lifetime. Top in the region lattice. ReStatic, @@ -906,7 +906,7 @@ impl DebruijnIndex { } /// Region utilities -impl<'tcx> RegionKind<'tcx> { +impl RegionKind { pub fn is_late_bound(&self) -> bool { match *self { ty::ReLateBound(..) => true, @@ -929,7 +929,7 @@ impl<'tcx> RegionKind<'tcx> { } /// Returns the depth of `self` from the (1-based) binding level `depth` - pub fn from_depth(&self, depth: u32) -> RegionKind<'tcx> { + pub fn from_depth(&self, depth: u32) -> RegionKind { match *self { ty::ReLateBound(debruijn, r) => ty::ReLateBound(DebruijnIndex { depth: debruijn.depth - (depth - 1) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 27cc5faaf20..8ca699339d3 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -458,7 +458,7 @@ impl fmt::Debug for ty::BoundRegion { } } -impl<'tcx> fmt::Debug for ty::RegionKind<'tcx> { +impl fmt::Debug for ty::RegionKind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { ty::ReEarlyBound(ref data) => { @@ -510,7 +510,7 @@ impl<'tcx> fmt::Debug for ty::ParameterEnvironment<'tcx> { } } -impl<'tcx> fmt::Display for ty::RegionKind<'tcx> { +impl<'tcx> fmt::Display for ty::RegionKind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if verbose() { return write!(f, "{:?}", *self); diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index adabbe11f5e..eeb5a3fb957 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -232,7 +232,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { }) } - pub fn each_in_scope_loan(&self, scope: region::CodeExtent<'tcx>, mut op: F) -> bool where + pub fn each_in_scope_loan(&self, scope: region::CodeExtent, mut op: F) -> bool where F: FnMut(&Loan<'tcx>) -> bool, { //! Like `each_issued_loan()`, but only considers loans that are @@ -248,7 +248,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { } fn each_in_scope_loan_affecting_path(&self, - scope: region::CodeExtent<'tcx>, + scope: region::CodeExtent, loan_path: &LoanPath<'tcx>, mut op: F) -> bool where @@ -708,7 +708,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { let mut ret = UseOk; self.each_in_scope_loan_affecting_path( - self.tcx().node_extent(expr_id), use_path, |loan| { + region::CodeExtent::Misc(expr_id), use_path, |loan| { if !compatible_borrow_kinds(loan.kind, borrow_kind) { ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span); false @@ -822,7 +822,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { // Check that we don't invalidate any outstanding loans if let Some(loan_path) = opt_loan_path(&assignee_cmt) { - let scope = self.tcx().node_extent(assignment_id); + let scope = region::CodeExtent::Misc(assignment_id); self.each_in_scope_loan_affecting_path(scope, &loan_path, |loan| { self.report_illegal_mutation(assignment_span, &loan_path, loan); false diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs index 12854d3c979..5fc5682a60b 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs @@ -24,7 +24,7 @@ use syntax_pos::Span; type R = Result<(),()>; pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, - item_scope: region::CodeExtent<'tcx>, + item_scope: region::CodeExtent, span: Span, cause: euv::LoanCause, cmt: mc::cmt<'tcx>, @@ -52,7 +52,7 @@ struct GuaranteeLifetimeContext<'a, 'tcx: 'a> { bccx: &'a BorrowckCtxt<'a, 'tcx>, // the scope of the function body for the enclosing item - item_scope: region::CodeExtent<'tcx>, + item_scope: region::CodeExtent, span: Span, cause: euv::LoanCause, diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index cbb6f7bce50..4cfee36359c 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -45,7 +45,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, bccx: bccx, infcx: &infcx, all_loans: Vec::new(), - item_ub: bccx.tcx.node_extent(body.node_id), + item_ub: region::CodeExtent::Misc(body.node_id), move_data: MoveData::new(), move_error_collector: move_error::MoveErrorCollector::new(), }; @@ -66,7 +66,7 @@ struct GatherLoanCtxt<'a, 'tcx: 'a> { all_loans: Vec>, /// `item_ub` is used as an upper-bound on the lifetime whenever we /// ask for the scope of an expression categorized as an upvar. - item_ub: region::CodeExtent<'tcx>, + item_ub: region::CodeExtent, } impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { @@ -376,7 +376,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { }; debug!("loan_scope = {:?}", loan_scope); - let borrow_scope = self.tcx().node_extent(borrow_id); + let borrow_scope = region::CodeExtent::Misc(borrow_id); let gen_scope = self.compute_gen_scope(borrow_scope, loan_scope); debug!("gen_scope = {:?}", gen_scope); @@ -455,9 +455,9 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { } pub fn compute_gen_scope(&self, - borrow_scope: region::CodeExtent<'tcx>, - loan_scope: region::CodeExtent<'tcx>) - -> region::CodeExtent<'tcx> { + borrow_scope: region::CodeExtent, + loan_scope: region::CodeExtent) + -> region::CodeExtent { //! Determine when to introduce the loan. Typically the loan //! is introduced at the point of the borrow, but in some cases, //! notably method arguments, the loan may be introduced only @@ -470,8 +470,8 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { } } - pub fn compute_kill_scope(&self, loan_scope: region::CodeExtent<'tcx>, lp: &LoanPath<'tcx>) - -> region::CodeExtent<'tcx> { + pub fn compute_kill_scope(&self, loan_scope: region::CodeExtent, lp: &LoanPath<'tcx>) + -> region::CodeExtent { //! Determine when the loan restrictions go out of scope. //! This is either when the lifetime expires or when the //! local variable which roots the loan-path goes out of scope, diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 07fd966f570..99df1431265 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -208,7 +208,7 @@ pub struct BorrowckCtxt<'a, 'tcx: 'a> { // Some in `borrowck_fn` and cleared later tables: &'a ty::TypeckTables<'tcx>, - region_maps: Rc>, + region_maps: Rc, owner_def_id: DefId, } @@ -228,13 +228,13 @@ pub struct Loan<'tcx> { /// cases, notably method arguments, the loan may be introduced /// only later, once it comes into scope. See also /// `GatherLoanCtxt::compute_gen_scope`. - gen_scope: region::CodeExtent<'tcx>, + gen_scope: region::CodeExtent, /// kill_scope indicates when the loan goes out of scope. This is /// either when the lifetime expires or when the local variable /// which roots the loan-path goes out of scope, whichever happens /// faster. See also `GatherLoanCtxt::compute_kill_scope`. - kill_scope: region::CodeExtent<'tcx>, + kill_scope: region::CodeExtent, span: Span, cause: euv::LoanCause, } @@ -334,12 +334,12 @@ pub fn closure_to_block(closure_id: ast::NodeId, } impl<'a, 'tcx> LoanPath<'tcx> { - pub fn kill_scope(&self, bccx: &BorrowckCtxt<'a, 'tcx>) -> region::CodeExtent<'tcx> { + pub fn kill_scope(&self, bccx: &BorrowckCtxt<'a, 'tcx>) -> region::CodeExtent { match self.kind { LpVar(local_id) => bccx.region_maps.var_scope(local_id), LpUpvar(upvar_id) => { let block_id = closure_to_block(upvar_id.closure_expr_id, bccx.tcx); - bccx.tcx.node_extent(block_id) + region::CodeExtent::Misc(block_id) } LpDowncast(ref base, _) | LpExtend(ref base, ..) => base.kill_scope(bccx), diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index a3dab6a938d..a18f91a9ee3 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -70,7 +70,7 @@ struct MatchVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::TypeckTables<'tcx>, param_env: &'a ty::ParameterEnvironment<'tcx>, - region_maps: &'a RegionMaps<'tcx>, + region_maps: &'a RegionMaps, } impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> { diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 1de6749200f..e2cbc480715 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -17,7 +17,6 @@ use rustc_resolve::MakeGlobMap; use rustc::middle::lang_items; use rustc::middle::free_region::FreeRegionMap; use rustc::middle::region::{CodeExtent, RegionMaps}; -use rustc::middle::region::CodeExtentData; use rustc::middle::resolve_lifetime; use rustc::middle::stability; use rustc::ty::subst::{Kind, Subst}; @@ -45,7 +44,7 @@ use rustc::hir; struct Env<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { infcx: &'a infer::InferCtxt<'a, 'gcx, 'tcx>, - region_maps: &'a mut RegionMaps<'tcx>, + region_maps: &'a mut RegionMaps, } struct RH<'a> { @@ -168,8 +167,8 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { self.infcx.tcx } - pub fn create_region_hierarchy(&mut self, rh: &RH, parent: CodeExtent<'tcx>) { - let me = self.tcx().intern_code_extent(CodeExtentData::Misc(rh.id)); + pub fn create_region_hierarchy(&mut self, rh: &RH, parent: CodeExtent) { + let me = CodeExtent::Misc(rh.id); self.region_maps.record_code_extent(me, Some(parent)); for child_rh in rh.sub { self.create_region_hierarchy(child_rh, me); @@ -181,7 +180,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { // children of 1, etc let node = ast::NodeId::from_u32; - let dscope = self.tcx().intern_code_extent(CodeExtentData::DestructionScope(node(1))); + let dscope = CodeExtent::DestructionScope(node(1)); self.region_maps.record_code_extent(dscope, None); self.create_region_hierarchy(&RH { id: node(1), @@ -327,7 +326,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { } pub fn t_rptr_scope(&self, id: u32) -> Ty<'tcx> { - let r = ty::ReScope(self.tcx().node_extent(ast::NodeId::from_u32(id))); + let r = ty::ReScope(CodeExtent::Misc(ast::NodeId::from_u32(id))); self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index ea845f722c3..819095e2628 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -21,7 +21,6 @@ use rustc::middle::cstore::LinkagePreference; use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::middle::lang_items; -use rustc::middle::region; use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; @@ -360,12 +359,6 @@ impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> } } -impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> { - fn specialized_decode(&mut self) -> Result, Self::Error> { - Ok(self.tcx().intern_code_extent(Decodable::decode(self)?)) - } -} - impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice>> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<&'tcx ty::Slice>, Self::Error> { Ok(self.tcx().mk_type_list((0..self.read_usize()?).map(|_| Decodable::decode(self)))?) diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs index f7534737edc..a3680214432 100644 --- a/src/librustc_mir/build/expr/as_operand.rs +++ b/src/librustc_mir/build/expr/as_operand.rs @@ -39,7 +39,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// The operand is known to be live until the end of `scope`. pub fn as_operand(&mut self, block: BasicBlock, - scope: Option>, + scope: Option, expr: M) -> BlockAnd> where M: Mirror<'tcx, Output = Expr<'tcx>> { @@ -49,7 +49,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn expr_as_operand(&mut self, mut block: BasicBlock, - scope: Option>, + scope: Option, expr: Expr<'tcx>) -> BlockAnd> { debug!("expr_as_operand(block={:?}, expr={:?})", block, expr); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 46e2408c38d..7b29cd970d7 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -38,7 +38,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } /// Compile `expr`, yielding an rvalue. - pub fn as_rvalue(&mut self, block: BasicBlock, scope: Option>, expr: M) + pub fn as_rvalue(&mut self, block: BasicBlock, scope: Option, expr: M) -> BlockAnd> where M: Mirror<'tcx, Output = Expr<'tcx>> { @@ -48,7 +48,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn expr_as_rvalue(&mut self, mut block: BasicBlock, - scope: Option>, + scope: Option, expr: Expr<'tcx>) -> BlockAnd> { debug!("expr_as_rvalue(block={:?}, expr={:?})", block, expr); diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index db4561af734..a334923546f 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -21,7 +21,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// up rvalues so as to freeze the value that will be consumed. pub fn as_temp(&mut self, block: BasicBlock, - temp_lifetime: Option>, + temp_lifetime: Option, expr: M) -> BlockAnd> where M: Mirror<'tcx, Output = Expr<'tcx>> @@ -32,7 +32,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn expr_as_temp(&mut self, mut block: BasicBlock, - temp_lifetime: Option>, + temp_lifetime: Option, expr: Expr<'tcx>) -> BlockAnd> { debug!("expr_as_temp(block={:?}, expr={:?})", block, expr); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index a3b1b24f20a..fb173e2487b 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -338,8 +338,8 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let span = tcx.hir.span(fn_id); let mut builder = Builder::new(hir.clone(), span, arguments.len(), return_ty); - let call_site_extent = tcx.call_site_extent(fn_id); - let arg_extent = tcx.parameter_extent(fn_id); + let call_site_extent = CodeExtent::CallSiteScope(body.id()); + let arg_extent = CodeExtent::ParameterScope(body.id()); let mut block = START_BLOCK; unpack!(block = builder.in_scope(call_site_extent, block, |builder| { unpack!(block = builder.in_scope(arg_extent, block, |builder| { @@ -480,7 +480,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn args_and_body(&mut self, mut block: BasicBlock, arguments: &[(Ty<'gcx>, Option<&'gcx hir::Pat>)], - argument_extent: CodeExtent<'tcx>, + argument_extent: CodeExtent, ast_body: &'gcx hir::Expr) -> BlockAnd<()> { diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 56ce4727d5f..ae47f4c4244 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -87,7 +87,7 @@ should go to. */ use build::{BlockAnd, BlockAndExtension, Builder, CFG}; -use rustc::middle::region::{CodeExtent, CodeExtentData}; +use rustc::middle::region::CodeExtent; use rustc::middle::lang_items; use rustc::middle::const_val::ConstVal; use rustc::ty::subst::{Kind, Subst}; @@ -102,7 +102,7 @@ pub struct Scope<'tcx> { visibility_scope: VisibilityScope, /// the extent of this scope within source code. - extent: CodeExtent<'tcx>, + extent: CodeExtent, /// Whether there's anything to do for the cleanup path, that is, /// when unwinding through this scope. This includes destructors, @@ -137,7 +137,7 @@ pub struct Scope<'tcx> { free: Option>, /// The cache for drop chain on “normal” exit into a particular BasicBlock. - cached_exits: FxHashMap<(BasicBlock, CodeExtent<'tcx>), BasicBlock>, + cached_exits: FxHashMap<(BasicBlock, CodeExtent), BasicBlock>, } struct DropData<'tcx> { @@ -180,7 +180,7 @@ struct FreeData<'tcx> { #[derive(Clone, Debug)] pub struct BreakableScope<'tcx> { /// Extent of the loop - pub extent: CodeExtent<'tcx>, + pub extent: CodeExtent, /// Where the body of the loop begins. `None` if block pub continue_block: Option, /// Block to branch into when the loop or block terminates (either by being `break`-en out @@ -271,7 +271,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Convenience wrapper that pushes a scope and then executes `f` /// to build its contents, popping the scope afterwards. pub fn in_scope(&mut self, - extent: CodeExtent<'tcx>, + extent: CodeExtent, mut block: BasicBlock, f: F) -> BlockAnd @@ -289,7 +289,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// scope and call `pop_scope` afterwards. Note that these two /// calls must be paired; using `in_scope` as a convenience /// wrapper maybe preferable. - pub fn push_scope(&mut self, extent: CodeExtent<'tcx>) { + pub fn push_scope(&mut self, extent: CodeExtent) { debug!("push_scope({:?})", extent); let vis_scope = self.visibility_scope; self.scopes.push(Scope { @@ -306,7 +306,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// drops onto the end of `block` that are needed. This must /// match 1-to-1 with `push_scope`. pub fn pop_scope(&mut self, - extent: CodeExtent<'tcx>, + extent: CodeExtent, mut block: BasicBlock) -> BlockAnd<()> { debug!("pop_scope({:?}, {:?})", extent, block); @@ -330,7 +330,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// module comment for details. pub fn exit_scope(&mut self, span: Span, - extent: CodeExtent<'tcx>, + extent: CodeExtent, mut block: BasicBlock, target: BasicBlock) { debug!("exit_scope(extent={:?}, block={:?}, target={:?})", extent, block, target); @@ -391,7 +391,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// resolving `break` and `continue`. pub fn find_breakable_scope(&mut self, span: Span, - label: CodeExtent<'tcx>) + label: CodeExtent) -> &mut BreakableScope<'tcx> { // find the loop-scope with the correct id self.breakable_scopes.iter_mut() @@ -411,12 +411,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Returns the extent of the scope which should be exited by a /// return. - pub fn extent_of_return_scope(&self) -> CodeExtent<'tcx> { + pub fn extent_of_return_scope(&self) -> CodeExtent { // The outermost scope (`scopes[0]`) will be the `CallSiteScope`. // We want `scopes[1]`, which is the `ParameterScope`. assert!(self.scopes.len() >= 2); - assert!(match *self.scopes[1].extent { - CodeExtentData::ParameterScope(_) => true, + assert!(match self.scopes[1].extent { + CodeExtent::ParameterScope(_) => true, _ => false, }); self.scopes[1].extent @@ -424,7 +424,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Returns the topmost active scope, which is known to be alive until /// the next scope expression. - pub fn topmost_scope(&self) -> CodeExtent<'tcx> { + pub fn topmost_scope(&self) -> CodeExtent { self.scopes.last().expect("topmost_scope: no scopes present").extent } @@ -434,7 +434,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// `extent`. pub fn schedule_drop(&mut self, span: Span, - extent: CodeExtent<'tcx>, + extent: CodeExtent, lvalue: &Lvalue<'tcx>, lvalue_ty: Ty<'tcx>) { let needs_drop = self.hir.needs_drop(lvalue_ty); @@ -524,7 +524,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// There may only be one “free” scheduled in any given scope. pub fn schedule_box_free(&mut self, span: Span, - extent: CodeExtent<'tcx>, + extent: CodeExtent, value: &Lvalue<'tcx>, item_ty: Ty<'tcx>) { for scope in self.scopes.iter_mut().rev() { diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index 2ec4a8a07df..920da306116 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -11,7 +11,7 @@ use hair::*; use hair::cx::Cx; use hair::cx::to_ref::ToRef; -use rustc::middle::region::{BlockRemainder, CodeExtentData}; +use rustc::middle::region::{BlockRemainder, CodeExtent}; use rustc::hir; use syntax::ast; @@ -24,7 +24,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { let stmts = mirror_stmts(cx, self.id, &*self.stmts); Block { targeted_by_break: self.targeted_by_break, - extent: cx.tcx.node_extent(self.id), + extent: CodeExtent::Misc(self.id), span: self.span, stmts: stmts, expr: self.expr.to_ref(), @@ -44,7 +44,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, result.push(StmtRef::Mirror(Box::new(Stmt { span: stmt.span, kind: StmtKind::Expr { - scope: cx.tcx.node_extent(id), + scope: CodeExtent::Misc(id), expr: expr.to_ref(), }, }))) @@ -55,19 +55,17 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // ignore for purposes of the MIR } hir::DeclLocal(ref local) => { - let remainder_extent = CodeExtentData::Remainder(BlockRemainder { + let remainder_extent = CodeExtent::Remainder(BlockRemainder { block: block_id, first_statement_index: index as u32, }); - let remainder_extent = - cx.tcx.intern_code_extent(remainder_extent); let pattern = Pattern::from_hir(cx.tcx, cx.tables(), &local.pat); result.push(StmtRef::Mirror(Box::new(Stmt { span: stmt.span, kind: StmtKind::Let { remainder_scope: remainder_extent, - init_scope: cx.tcx.node_extent(id), + init_scope: CodeExtent::Misc(id), pattern: pattern, initializer: local.init.to_ref(), }, @@ -84,7 +82,7 @@ pub fn to_expr_ref<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, block: &'tcx hir::Block) -> ExprRef<'tcx> { let block_ty = cx.tables().node_id_to_type(block.id); - let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, block.id); + let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(block.id); let expr = Expr { ty: block_ty, temp_lifetime: temp_lifetime, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index a692e987761..b180d982e86 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -25,8 +25,8 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { type Output = Expr<'tcx>; fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> { - let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, self.id); - let expr_extent = cx.tcx.node_extent(self.id); + let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(self.id); + let expr_extent = CodeExtent::Misc(self.id); debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span); @@ -237,7 +237,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr) -> Expr<'tcx> { let expr_ty = cx.tables().expr_ty(expr); - let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id); + let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id); let kind = match expr.node { // Here comes the interesting stuff: @@ -609,7 +609,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, match dest.target_id { hir::ScopeTarget::Block(target_id) | hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(target_id)) => ExprKind::Break { - label: cx.tcx.node_extent(target_id), + label: CodeExtent::Misc(target_id), value: value.to_ref(), }, hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) => @@ -620,7 +620,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, match dest.target_id { hir::ScopeTarget::Block(_) => bug!("cannot continue to blocks"), hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(loop_id)) => ExprKind::Continue { - label: cx.tcx.node_extent(loop_id), + label: CodeExtent::Misc(loop_id), }, hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) => bug!("invalid loop id for continue: {}", err) @@ -685,7 +685,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprBox(ref value) => { ExprKind::Box { value: value.to_ref(), - value_extents: cx.tcx.node_extent(value.id), + value_extents: CodeExtent::Misc(value.id), } } hir::ExprArray(ref fields) => ExprKind::Array { fields: fields.to_ref() }, @@ -706,7 +706,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, method_call: ty::MethodCall) -> Expr<'tcx> { let callee = cx.tables().method_map[&method_call]; - let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id); + let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id); Expr { temp_lifetime: temp_lifetime, temp_lifetime_was_shrunk: was_shrunk, @@ -790,7 +790,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr, def: Def) -> ExprKind<'tcx> { - let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id); + let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id); match def { Def::Local(def_id) => { @@ -965,7 +965,7 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, PassArgs::ByRef => { let region = cx.tcx.node_scope_region(expr.id); let (temp_lifetime, was_shrunk) = - cx.region_maps.temporary_scope2(cx.tcx, expr.id); + cx.region_maps.temporary_scope2(expr.id); argrefs.extend(args.iter() .map(|arg| { let arg_ty = cx.tables().expr_ty_adjusted(arg); @@ -1017,7 +1017,7 @@ fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // construct the complete expression `foo()` for the overloaded call, // which will yield the &T type - let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id); + let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id); let ref_kind = overloaded_operator(cx, expr, method_call, pass_args, receiver, args); let ref_expr = Expr { temp_lifetime: temp_lifetime, @@ -1042,7 +1042,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, closure_expr_id: closure_expr.id, }; let upvar_capture = cx.tables().upvar_capture(upvar_id).unwrap(); - let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, closure_expr.id); + let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(closure_expr.id); let var_ty = cx.tables().node_id_to_type(id_var); let captured_var = Expr { temp_lifetime: temp_lifetime, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index ee8547e5dd6..9ffce18fe15 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -35,7 +35,7 @@ use std::rc::Rc; pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - pub region_maps: Rc>, + pub region_maps: Rc, constness: hir::Constness, /// True if this constant/function needs overflow checks. diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 0e8992e62ea..1af9d722599 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -32,7 +32,7 @@ pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPatt #[derive(Clone, Debug)] pub struct Block<'tcx> { pub targeted_by_break: bool, - pub extent: CodeExtent<'tcx>, + pub extent: CodeExtent, pub span: Span, pub stmts: Vec>, pub expr: Option>, @@ -53,7 +53,7 @@ pub struct Stmt<'tcx> { pub enum StmtKind<'tcx> { Expr { /// scope for this statement; may be used as lifetime of temporaries - scope: CodeExtent<'tcx>, + scope: CodeExtent, /// expression being evaluated in this statement expr: ExprRef<'tcx>, @@ -62,11 +62,11 @@ pub enum StmtKind<'tcx> { Let { /// scope for variables bound in this let; covers this and /// remaining statements in block - remainder_scope: CodeExtent<'tcx>, + remainder_scope: CodeExtent, /// scope for the initialization itself; might be used as /// lifetime of temporaries - init_scope: CodeExtent<'tcx>, + init_scope: CodeExtent, /// let = ... pattern: Pattern<'tcx>, @@ -97,7 +97,7 @@ pub struct Expr<'tcx> { /// lifetime of this expression if it should be spilled into a /// temporary; should be None only if in a constant context - pub temp_lifetime: Option>, + pub temp_lifetime: Option, /// whether this temp lifetime was shrunk by #36082. pub temp_lifetime_was_shrunk: bool, @@ -112,12 +112,12 @@ pub struct Expr<'tcx> { #[derive(Clone, Debug)] pub enum ExprKind<'tcx> { Scope { - extent: CodeExtent<'tcx>, + extent: CodeExtent, value: ExprRef<'tcx>, }, Box { value: ExprRef<'tcx>, - value_extents: CodeExtent<'tcx>, + value_extents: CodeExtent, }, Call { ty: ty::Ty<'tcx>, @@ -210,11 +210,11 @@ pub enum ExprKind<'tcx> { arg: ExprRef<'tcx>, }, Break { - label: CodeExtent<'tcx>, + label: CodeExtent, value: Option>, }, Continue { - label: CodeExtent<'tcx>, + label: CodeExtent, }, Return { value: Option>, diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 8e3329e2720..e0293325596 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -270,7 +270,7 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>( rcx: &mut RegionCtxt<'a, 'gcx, 'tcx>, ty: ty::Ty<'tcx>, span: Span, - scope: region::CodeExtent<'tcx>) + scope: region::CodeExtent) -> Result<(), ErrorReported> { debug!("check_safety_of_destructor_if_necessary typ: {:?} scope: {:?}", diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3755dfd3f40..70d2867c08c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -88,6 +88,7 @@ use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_back::slice::ref_slice; use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin}; use rustc::infer::type_variable::{TypeVariableOrigin}; +use rustc::middle::region::CodeExtent; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal}; use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue}; @@ -560,12 +561,8 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { 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 - } + let implicit_region_bound = body_id.map(|body| { + tcx.mk_region(ty::ReScope(CodeExtent::CallSiteScope(body))) }); Inherited { diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 3da01764243..754bd288bfa 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -178,7 +178,7 @@ pub struct RegionCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>, - pub region_maps: Rc>, + pub region_maps: Rc, free_region_map: FreeRegionMap<'tcx>, @@ -186,7 +186,7 @@ pub struct RegionCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { body_id: ast::NodeId, // call_site scope of innermost fn - call_site_scope: Option>, + call_site_scope: Option, // id of innermost fn or loop repeating_scope: ast::NodeId, @@ -224,8 +224,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { } } - fn set_call_site_scope(&mut self, call_site_scope: Option>) - -> Option> { + fn set_call_site_scope(&mut self, call_site_scope: Option) + -> Option { mem::replace(&mut self.call_site_scope, call_site_scope) } @@ -286,7 +286,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let body_id = body.id(); - let call_site = self.tcx.call_site_extent(id); + let call_site = CodeExtent::CallSiteScope(body_id); let old_call_site_scope = self.set_call_site_scope(Some(call_site)); let fn_sig = { @@ -311,7 +311,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let old_body_id = self.set_body_id(body_id.node_id); self.relate_free_regions(&fn_sig_tys[..], body_id.node_id, span); - self.link_fn_args(self.tcx.node_extent(body_id.node_id), &body.arguments); + self.link_fn_args(CodeExtent::Misc(body_id.node_id), &body.arguments); self.visit_body(body); self.visit_region_obligations(body_id.node_id); @@ -877,7 +877,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // call occurs. // // FIXME(#6268) to support nested method calls, should be callee_id - let callee_scope = self.tcx.node_extent(call_expr.id); + let callee_scope = CodeExtent::Misc(call_expr.id); let callee_region = self.tcx.mk_region(ty::ReScope(callee_scope)); debug!("callee_region={:?}", callee_region); @@ -1030,7 +1030,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { debug!("constrain_index(index_expr=?, indexed_ty={}", self.ty_to_string(indexed_ty)); - let r_index_expr = ty::ReScope(self.tcx.node_extent(index_expr.id)); + let r_index_expr = ty::ReScope(CodeExtent::Misc(index_expr.id)); if let ty::TyRef(r_ptr, mt) = indexed_ty.sty { match mt.ty.sty { ty::TySlice(_) | ty::TyStr => { @@ -1110,7 +1110,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { /// Computes the guarantors for any ref bindings in a match and /// then ensures that the lifetime of the resulting pointer is /// linked to the lifetime of its guarantor (if any). - fn link_fn_args(&self, body_scope: CodeExtent<'tcx>, args: &[hir::Arg]) { + fn link_fn_args(&self, body_scope: CodeExtent, args: &[hir::Arg]) { debug!("regionck::link_fn_args(body_scope={:?})", body_scope); let mc = &mc::MemCategorizationContext::new(self, &self.region_maps); for arg in args { @@ -1176,7 +1176,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { /// must outlive `callee_scope`. fn link_by_ref(&self, expr: &hir::Expr, - callee_scope: CodeExtent<'tcx>) { + callee_scope: CodeExtent) { debug!("link_by_ref(expr={:?}, callee_scope={:?})", expr, callee_scope); let mc = mc::MemCategorizationContext::new(self, &self.region_maps); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2dde6d9d4ee..61f941e57b2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -820,7 +820,7 @@ impl Clean for ty::RegionParameterDef { } } -impl<'tcx> Clean> for ty::RegionKind<'tcx> { +impl Clean> for ty::RegionKind { fn clean(&self, cx: &DocContext) -> Option { match *self { ty::ReStatic => Some(Lifetime::statik()), From 6da4123f5f819608fce49258bfa4f74fe195806b Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 May 2017 17:18:23 +0300 Subject: [PATCH 10/10] rustc: don't keep a second reference to the HIR map in middle::region. --- src/librustc/middle/region.rs | 47 +++++++++++++++++------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 331683381a4..2d632e3feb5 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -264,12 +264,10 @@ struct RegionResolutionVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, // Generated maps: - region_maps: &'a mut RegionMaps, + region_maps: RegionMaps, cx: Context, - map: &'a hir_map::Map<'tcx>, - /// `terminating_scopes` is a set containing the ids of each /// statement, or conditional/repeating expression. These scopes /// are calling "terminating scopes" because, when attempting to @@ -1105,7 +1103,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> { fn visit_body(&mut self, body: &'tcx hir::Body) { let body_id = body.id(); - let owner_id = self.map.body_owner(body_id); + let owner_id = self.tcx.hir.body_owner(body_id); debug!("visit_body(id={:?}, span={:?}, body.id={:?}, cx.parent={:?})", owner_id, @@ -1170,27 +1168,11 @@ fn region_maps<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) return tcx.region_maps(closure_base_def_id); } - let mut maps = RegionMaps::new(); - let id = tcx.hir.as_local_node_id(def_id).unwrap(); - if let Some(body) = tcx.hir.maybe_body_owned_by(id) { - maps.root_body = Some(body); - - // If the item is an associated const or a method, - // record its impl/trait parent, as it can also have - // lifetime parameters free in this body. - match tcx.hir.get(id) { - hir::map::NodeImplItem(_) | - hir::map::NodeTraitItem(_) => { - maps.root_parent = Some(tcx.hir.get_parent(id)); - } - _ => {} - } - + let maps = if let Some(body) = tcx.hir.maybe_body_owned_by(id) { let mut visitor = RegionResolutionVisitor { - tcx: tcx, - region_maps: &mut maps, - map: &tcx.hir, + tcx, + region_maps: RegionMaps::new(), cx: Context { root_id: None, parent: None, @@ -1199,8 +1181,25 @@ fn region_maps<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) terminating_scopes: NodeSet(), }; + visitor.region_maps.root_body = Some(body); + + // If the item is an associated const or a method, + // record its impl/trait parent, as it can also have + // lifetime parameters free in this body. + match tcx.hir.get(id) { + hir::map::NodeImplItem(_) | + hir::map::NodeTraitItem(_) => { + visitor.region_maps.root_parent = Some(tcx.hir.get_parent(id)); + } + _ => {} + } + visitor.visit_body(tcx.hir.body(body)); - } + + visitor.region_maps + } else { + RegionMaps::new() + }; Rc::new(maps) }