1
Fork 0

Use DefIndex instead of NodeId in UpvarId.

This commit is contained in:
Michael Woerister 2017-08-08 14:34:37 +02:00
parent a8cf6cc6db
commit 4dcc3a4aae
13 changed files with 142 additions and 85 deletions

View file

@ -11,6 +11,7 @@
//! This module contains `HashStable` implementations for various data types //! This module contains `HashStable` implementations for various data types
//! from rustc::ty in no particular order. //! from rustc::ty in no particular order.
use hir::def_id::DefId;
use ich::{self, StableHashingContext, NodeIdHashingMode}; use ich::{self, StableHashingContext, NodeIdHashingMode};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
StableHasherResult}; StableHasherResult};
@ -618,7 +619,7 @@ for ty::TypeckTables<'gcx> {
hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
hasher: &mut StableHasher<W>) { hasher: &mut StableHasher<W>) {
let ty::TypeckTables { let ty::TypeckTables {
local_id_root: _, local_id_root,
ref type_dependent_defs, ref type_dependent_defs,
ref node_types, ref node_types,
ref node_substs, ref node_substs,
@ -649,8 +650,14 @@ for ty::TypeckTables<'gcx> {
closure_expr_id closure_expr_id
} = *up_var_id; } = *up_var_id;
let var_def_id = hcx.tcx().hir.local_def_id(var_id); let var_def_id = DefId {
let closure_def_id = hcx.tcx().hir.local_def_id(closure_expr_id); krate: local_id_root.krate,
index: var_id,
};
let closure_def_id = DefId {
krate: local_id_root.krate,
index: closure_expr_id,
};
(hcx.def_path_hash(var_def_id), hcx.def_path_hash(closure_def_id)) (hcx.def_path_hash(var_def_id), hcx.def_path_hash(closure_def_id))
}); });

View file

@ -913,7 +913,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
} }
infer::UpvarRegion(ref upvar_id, _) => { infer::UpvarRegion(ref upvar_id, _) => {
format!(" for capture of `{}` by closure", format!(" for capture of `{}` by closure",
self.tcx.local_var_name_str(upvar_id.var_id).to_string()) self.tcx.local_var_name_str_def_index(upvar_id.var_id))
} }
}; };

View file

@ -45,8 +45,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
err.span_note(span, err.span_note(span,
&format!("...so that closure can access `{}`", &format!("...so that closure can access `{}`",
self.tcx self.tcx
.local_var_name_str(upvar_id.var_id) .local_var_name_str_def_index(upvar_id.var_id)));
.to_string()));
} }
infer::InfStackClosure(span) => { infer::InfStackClosure(span) => {
err.span_note(span, "...so that closure does not outlive its stack frame"); err.span_note(span, "...so that closure does not outlive its stack frame");
@ -176,18 +175,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
E0313, E0313,
"lifetime of borrowed pointer outlives lifetime \ "lifetime of borrowed pointer outlives lifetime \
of captured variable `{}`...", of captured variable `{}`...",
self.tcx.local_var_name_str(upvar_id.var_id)); self.tcx
.local_var_name_str_def_index(upvar_id.var_id));
self.tcx.note_and_explain_region(&mut err, self.tcx.note_and_explain_region(&mut err,
"...the borrowed pointer is valid for ", "...the borrowed pointer is valid for ",
sub, sub,
"..."); "...");
self.tcx self.tcx
.note_and_explain_region(&mut err, .note_and_explain_region(
&format!("...but `{}` is only valid for ", &mut err,
self.tcx &format!("...but `{}` is only valid for ",
.local_var_name_str(upvar_id.var_id)), self.tcx.local_var_name_str_def_index(upvar_id.var_id)),
sup, sup,
""); "");
err err
} }
infer::InfStackClosure(span) => { infer::InfStackClosure(span) => {

View file

@ -890,10 +890,13 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
self.tcx().with_freevars(closure_expr.id, |freevars| { self.tcx().with_freevars(closure_expr.id, |freevars| {
for freevar in freevars { for freevar in freevars {
let def_id = freevar.def.def_id(); let var_def_id = freevar.def.def_id();
let id_var = self.tcx().hir.as_local_node_id(def_id).unwrap(); debug_assert!(var_def_id.is_local());
let upvar_id = ty::UpvarId { var_id: id_var, let closure_def_id = self.tcx().hir.local_def_id(closure_expr.id);
closure_expr_id: closure_expr.id }; let upvar_id = ty::UpvarId {
var_id: var_def_id.index,
closure_expr_id: closure_def_id.index
};
let upvar_capture = self.mc.tables.upvar_capture(upvar_id); let upvar_capture = self.mc.tables.upvar_capture(upvar_id);
let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id, let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id,
fn_decl_span, fn_decl_span,

View file

@ -70,7 +70,7 @@ pub use self::Note::*;
use self::Aliasability::*; use self::Aliasability::*;
use middle::region::RegionMaps; use middle::region::RegionMaps;
use hir::def_id::DefId; use hir::def_id::{DefId, DefIndex};
use hir::map as hir_map; use hir::map as hir_map;
use infer::InferCtxt; use infer::InferCtxt;
use hir::def::{Def, CtorKind}; use hir::def::{Def, CtorKind};
@ -190,7 +190,7 @@ pub type cmt<'tcx> = Rc<cmt_<'tcx>>;
pub enum ImmutabilityBlame<'tcx> { pub enum ImmutabilityBlame<'tcx> {
ImmLocal(ast::NodeId), ImmLocal(ast::NodeId),
ClosureEnv(ast::NodeId), ClosureEnv(DefIndex),
LocalDeref(ast::NodeId), LocalDeref(ast::NodeId),
AdtFieldDeref(&'tcx ty::AdtDef, &'tcx ty::FieldDef) AdtFieldDeref(&'tcx ty::AdtDef, &'tcx ty::FieldDef)
} }
@ -728,8 +728,13 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
None => span_bug!(span, "missing closure kind") None => span_bug!(span, "missing closure kind")
}; };
let upvar_id = ty::UpvarId { var_id, let closure_expr_def_index = self.tcx.hir.local_def_id(fn_node_id).index;
closure_expr_id: fn_node_id }; let var_def_index = self.tcx.hir.local_def_id(var_id).index;
let upvar_id = ty::UpvarId {
var_id: var_def_index,
closure_expr_id: closure_expr_def_index
};
let var_hir_id = self.tcx.hir.node_to_hir_id(var_id); let var_hir_id = self.tcx.hir.node_to_hir_id(var_id);
let var_ty = self.node_ty(var_hir_id)?; let var_ty = self.node_ty(var_hir_id)?;
@ -766,8 +771,6 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
// If this is a by-ref capture, then the upvar we loaded is // If this is a by-ref capture, then the upvar we loaded is
// actually a reference, so we have to add an implicit deref // actually a reference, so we have to add an implicit deref
// for that. // for that.
let upvar_id = ty::UpvarId { var_id,
closure_expr_id: fn_node_id };
let upvar_capture = self.tables.upvar_capture(upvar_id); let upvar_capture = self.tables.upvar_capture(upvar_id);
let cmt_result = match upvar_capture { let cmt_result = match upvar_capture {
ty::UpvarCapture::ByValue => { ty::UpvarCapture::ByValue => {
@ -805,7 +808,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
// The environment of a closure is guaranteed to // The environment of a closure is guaranteed to
// outlive any bindings introduced in the body of the // outlive any bindings introduced in the body of the
// closure itself. // closure itself.
scope: self.tcx.hir.local_def_id(upvar_id.closure_expr_id), scope: DefId::local(upvar_id.closure_expr_id),
bound_region: ty::BrEnv bound_region: ty::BrEnv
})); }));

View file

@ -572,8 +572,8 @@ impl<T> Slice<T> {
/// by the upvar) and the id of the closure expression. /// by the upvar) and the id of the closure expression.
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct UpvarId { pub struct UpvarId {
pub var_id: NodeId, pub var_id: DefIndex,
pub closure_expr_id: NodeId, pub closure_expr_id: DefIndex,
} }
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, Copy)] #[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, Copy)]
@ -1983,6 +1983,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
} }
} }
pub fn local_var_name_str_def_index(self, def_index: DefIndex) -> InternedString {
let node_id = self.hir.as_local_node_id(DefId::local(def_index)).unwrap();
self.local_var_name_str(node_id)
}
pub fn expr_is_lval(self, expr: &hir::Expr) -> bool { pub fn expr_is_lval(self, expr: &hir::Expr) -> bool {
match expr.node { match expr.node {
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => { hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {

View file

@ -864,9 +864,9 @@ impl<'tcx> fmt::Display for ty::TyS<'tcx> {
impl fmt::Debug for ty::UpvarId { impl fmt::Debug for ty::UpvarId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "UpvarId({};`{}`;{})", write!(f, "UpvarId({:?};`{}`;{:?})",
self.var_id, self.var_id,
ty::tls::with(|tcx| tcx.local_var_name_str(self.var_id)), ty::tls::with(|tcx| tcx.local_var_name_str_def_index(self.var_id)),
self.closure_expr_id) self.closure_expr_id)
} }
} }

View file

@ -93,11 +93,11 @@ fn report_move_errors<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, errors: &Vec<Move
} }
} }
if let NoteClosureEnv(upvar_id) = error.move_from.note { if let NoteClosureEnv(upvar_id) = error.move_from.note {
err.span_label(bccx.tcx.hir.span(upvar_id.var_id), let var_node_id = bccx.tcx.hir.def_index_to_node_id(upvar_id.var_id);
err.span_label(bccx.tcx.hir.span(var_node_id),
"captured outer variable"); "captured outer variable");
} }
err.emit(); err.emit();
} }
} }

View file

@ -27,7 +27,7 @@ use rustc::middle::dataflow::DataFlowContext;
use rustc::middle::dataflow::BitwiseOperator; use rustc::middle::dataflow::BitwiseOperator;
use rustc::middle::dataflow::DataFlowOperator; use rustc::middle::dataflow::DataFlowOperator;
use rustc::middle::dataflow::KillFrom; use rustc::middle::dataflow::KillFrom;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::{DefId, DefIndex};
use rustc::middle::expr_use_visitor as euv; use rustc::middle::expr_use_visitor as euv;
use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization as mc;
use rustc::middle::mem_categorization::Categorization; use rustc::middle::mem_categorization::Categorization;
@ -323,8 +323,9 @@ pub enum LoanPathElem<'tcx> {
LpInterior(Option<DefId>, InteriorKind), LpInterior(Option<DefId>, InteriorKind),
} }
pub fn closure_to_block(closure_id: ast::NodeId, fn closure_to_block(closure_id: DefIndex,
tcx: TyCtxt) -> ast::NodeId { tcx: TyCtxt) -> ast::NodeId {
let closure_id = tcx.hir.def_index_to_node_id(closure_id);
match tcx.hir.get(closure_id) { match tcx.hir.get(closure_id) {
hir_map::NodeExpr(expr) => match expr.node { hir_map::NodeExpr(expr) => match expr.node {
hir::ExprClosure(.., body_id, _) => { hir::ExprClosure(.., body_id, _) => {
@ -845,7 +846,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
} else { } else {
"consider changing this closure to take self by mutable reference" "consider changing this closure to take self by mutable reference"
}; };
err.span_help(self.tcx.hir.span(id), help); let node_id = self.tcx.hir.def_index_to_node_id(id);
err.span_help(self.tcx.hir.span(node_id), help);
err err
} }
_ => { _ => {
@ -1181,7 +1183,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
_ => bug!() _ => bug!()
}; };
if kind == ty::ClosureKind::Fn { if kind == ty::ClosureKind::Fn {
db.span_help(self.tcx.hir.span(upvar_id.closure_expr_id), let closure_node_id =
self.tcx.hir.def_index_to_node_id(upvar_id.closure_expr_id);
db.span_help(self.tcx.hir.span(closure_node_id),
"consider changing this closure to take \ "consider changing this closure to take \
self by mutable reference"); self by mutable reference");
} }
@ -1214,7 +1218,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
loan_path: &LoanPath<'tcx>, loan_path: &LoanPath<'tcx>,
out: &mut String) { out: &mut String) {
match loan_path.kind { match loan_path.kind {
LpUpvar(ty::UpvarId{ var_id: id, closure_expr_id: _ }) | LpUpvar(ty::UpvarId { var_id: id, closure_expr_id: _ }) => {
out.push_str(&self.tcx.local_var_name_str_def_index(id));
}
LpVar(id) => { LpVar(id) => {
out.push_str(&self.tcx.local_var_name_str(id)); out.push_str(&self.tcx.local_var_name_str(id));
} }
@ -1352,8 +1358,11 @@ impl<'tcx> fmt::Debug for LoanPath<'tcx> {
} }
LpUpvar(ty::UpvarId{ var_id, closure_expr_id }) => { LpUpvar(ty::UpvarId{ var_id, closure_expr_id }) => {
let s = ty::tls::with(|tcx| tcx.hir.node_to_string(var_id)); let s = ty::tls::with(|tcx| {
write!(f, "$({} captured by id={})", s, closure_expr_id) let var_node_id = tcx.hir.def_index_to_node_id(var_id);
tcx.hir.node_to_string(var_node_id)
});
write!(f, "$({} captured by id={:?})", s, closure_expr_id)
} }
LpDowncast(ref lp, variant_def_id) => { LpDowncast(ref lp, variant_def_id) => {
@ -1384,7 +1393,10 @@ impl<'tcx> fmt::Display for LoanPath<'tcx> {
} }
LpUpvar(ty::UpvarId{ var_id, closure_expr_id: _ }) => { LpUpvar(ty::UpvarId{ var_id, closure_expr_id: _ }) => {
let s = ty::tls::with(|tcx| tcx.hir.node_to_user_string(var_id)); let s = ty::tls::with(|tcx| {
let var_node_id = tcx.hir.def_index_to_node_id(var_id);
tcx.hir.node_to_string(var_node_id)
});
write!(f, "$({} captured by closure)", s) write!(f, "$({} captured by closure)", s)
} }

View file

@ -368,10 +368,12 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
// Gather the upvars of a closure, if any. // Gather the upvars of a closure, if any.
let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| { let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| {
freevars.iter().map(|fv| { freevars.iter().map(|fv| {
let var_id = tcx.hir.as_local_node_id(fv.def.def_id()).unwrap(); let var_def_id = fv.def.def_id();
let var_node_id = tcx.hir.as_local_node_id(var_def_id).unwrap();
let closure_expr_id = tcx.hir.local_def_id(fn_id).index;
let capture = hir.tables().upvar_capture(ty::UpvarId { let capture = hir.tables().upvar_capture(ty::UpvarId {
var_id: var_id, var_id: var_def_id.index,
closure_expr_id: fn_id closure_expr_id,
}); });
let by_ref = match capture { let by_ref = match capture {
ty::UpvarCapture::ByValue => false, ty::UpvarCapture::ByValue => false,
@ -381,7 +383,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
debug_name: keywords::Invalid.name(), debug_name: keywords::Invalid.name(),
by_ref: by_ref by_ref: by_ref
}; };
if let Some(hir::map::NodeLocal(pat)) = tcx.hir.find(var_id) { if let Some(hir::map::NodeLocal(pat)) = tcx.hir.find(var_node_id) {
if let hir::PatKind::Binding(_, _, ref ident, _) = pat.node { if let hir::PatKind::Binding(_, _, ref ident, _) = pat.node {
decl.debug_name = ident.node; decl.debug_name = ident.node;
} }

View file

@ -684,8 +684,8 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
ExprKind::VarRef { id: node_id } ExprKind::VarRef { id: node_id }
} }
Def::Upvar(def_id, index, closure_expr_id) => { Def::Upvar(var_def_id, index, closure_expr_id) => {
let id_var = cx.tcx.hir.as_local_node_id(def_id).unwrap(); let id_var = cx.tcx.hir.as_local_node_id(var_def_id).unwrap();
debug!("convert_var(upvar({:?}, {:?}, {:?}))", debug!("convert_var(upvar({:?}, {:?}, {:?}))",
id_var, id_var,
index, index,
@ -768,8 +768,8 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
// ...but the upvar might be an `&T` or `&mut T` capture, at which // ...but the upvar might be an `&T` or `&mut T` capture, at which
// point we need an implicit deref // point we need an implicit deref
let upvar_id = ty::UpvarId { let upvar_id = ty::UpvarId {
var_id: id_var, var_id: var_def_id.index,
closure_expr_id: closure_expr_id, closure_expr_id: closure_def_id.index,
}; };
match cx.tables().upvar_capture(upvar_id) { match cx.tables().upvar_capture(upvar_id) {
ty::UpvarCapture::ByValue => field_kind, ty::UpvarCapture::ByValue => field_kind,
@ -880,15 +880,16 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
freevar: &hir::Freevar, freevar: &hir::Freevar,
freevar_ty: Ty<'tcx>) freevar_ty: Ty<'tcx>)
-> ExprRef<'tcx> { -> ExprRef<'tcx> {
let id_var = cx.tcx.hir.as_local_node_id(freevar.def.def_id()).unwrap(); let var_def_id = freevar.def.def_id();
let var_node_id = cx.tcx.hir.as_local_node_id(var_def_id).unwrap();
let upvar_id = ty::UpvarId { let upvar_id = ty::UpvarId {
var_id: id_var, var_id: var_def_id.index,
closure_expr_id: closure_expr.id, closure_expr_id: cx.tcx.hir.local_def_id(closure_expr.id).index,
}; };
let upvar_capture = cx.tables().upvar_capture(upvar_id); let upvar_capture = cx.tables().upvar_capture(upvar_id);
let temp_lifetime = cx.region_maps.temporary_scope(closure_expr.id); let temp_lifetime = cx.region_maps.temporary_scope(closure_expr.id);
let var_ty = cx.tables() let var_ty = cx.tables()
.node_id_to_type(cx.tcx.hir.node_to_hir_id(id_var)); .node_id_to_type(cx.tcx.hir.node_to_hir_id(var_node_id));
let captured_var = Expr { let captured_var = Expr {
temp_lifetime: temp_lifetime, temp_lifetime: temp_lifetime,
ty: var_ty, ty: var_ty,

View file

@ -50,8 +50,9 @@ use rustc::infer::UpvarRegion;
use syntax::ast; use syntax::ast;
use syntax_pos::Span; use syntax_pos::Span;
use rustc::hir; use rustc::hir;
use rustc::hir::def_id::DefIndex;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::util::nodemap::NodeMap; use rustc::util::nodemap::FxHashMap;
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
@ -90,7 +91,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for InferBorrowKindVisitor<'a, 'gcx, 'tcx> {
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
fn analyze_closure(&self, fn analyze_closure(&self,
(id, hir_id): (ast::NodeId, hir::HirId), (closure_node_id, closure_hir_id): (ast::NodeId, hir::HirId),
span: Span, span: Span,
body: &hir::Body, body: &hir::Body,
capture_clause: hir::CaptureClause) { capture_clause: hir::CaptureClause) {
@ -98,23 +99,29 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
* Analysis starting point. * Analysis starting point.
*/ */
debug!("analyze_closure(id={:?}, body.id={:?})", id, body.id()); debug!("analyze_closure(id={:?}, body.id={:?})", closure_node_id, body.id());
let infer_kind = match self.tables.borrow_mut().closure_kinds.entry(hir_id.local_id) { let infer_kind = match self.tables
.borrow_mut()
.closure_kinds
.entry(closure_hir_id.local_id) {
Entry::Occupied(_) => false, Entry::Occupied(_) => false,
Entry::Vacant(entry) => { Entry::Vacant(entry) => {
debug!("check_closure: adding closure {:?} as Fn", id); debug!("check_closure: adding closure {:?} as Fn", closure_node_id);
entry.insert((ty::ClosureKind::Fn, None)); entry.insert((ty::ClosureKind::Fn, None));
true true
} }
}; };
self.tcx.with_freevars(id, |freevars| { let closure_def_id = self.tcx.hir.local_def_id(closure_node_id);
self.tcx.with_freevars(closure_node_id, |freevars| {
for freevar in freevars { for freevar in freevars {
let def_id = freevar.def.def_id(); let var_def_id = freevar.def.def_id();
let var_node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); let upvar_id = ty::UpvarId {
let upvar_id = ty::UpvarId { var_id: var_node_id, var_id: var_def_id.index,
closure_expr_id: id }; closure_expr_id: closure_def_id.index,
};
debug!("seed upvar_id {:?}", upvar_id); debug!("seed upvar_id {:?}", upvar_id);
let capture_kind = match capture_clause { let capture_kind = match capture_clause {
@ -139,7 +146,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let region_maps = &self.tcx.region_maps(body_owner_def_id); let region_maps = &self.tcx.region_maps(body_owner_def_id);
let mut delegate = InferBorrowKind { let mut delegate = InferBorrowKind {
fcx: self, fcx: self,
adjust_closure_kinds: NodeMap(), adjust_closure_kinds: FxHashMap(),
adjust_upvar_captures: ty::UpvarCaptureMap::default(), adjust_upvar_captures: ty::UpvarCaptureMap::default(),
}; };
euv::ExprUseVisitor::with_infer(&mut delegate, euv::ExprUseVisitor::with_infer(&mut delegate,
@ -151,8 +158,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Write the adjusted values back into the main tables. // Write the adjusted values back into the main tables.
if infer_kind { if infer_kind {
if let Some(kind) = delegate.adjust_closure_kinds.remove(&id) { if let Some(kind) = delegate.adjust_closure_kinds
self.tables.borrow_mut().closure_kinds.insert(hir_id.local_id, kind); .remove(&closure_def_id.index) {
self.tables
.borrow_mut()
.closure_kinds
.insert(closure_hir_id.local_id, kind);
} }
} }
self.tables.borrow_mut().upvar_capture_map.extend( self.tables.borrow_mut().upvar_capture_map.extend(
@ -172,20 +183,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// inference algorithm will reject it). // inference algorithm will reject it).
// Extract the type variables UV0...UVn. // Extract the type variables UV0...UVn.
let (def_id, closure_substs) = match self.node_ty(hir_id).sty { let (def_id, closure_substs) = match self.node_ty(closure_hir_id).sty {
ty::TyClosure(def_id, substs) => (def_id, substs), ty::TyClosure(def_id, substs) => (def_id, substs),
ref t => { ref t => {
span_bug!( span_bug!(
span, span,
"type of closure expr {:?} is not a closure {:?}", "type of closure expr {:?} is not a closure {:?}",
id, t); closure_node_id, t);
} }
}; };
// Equate the type variables with the actual types. // Equate the type variables with the actual types.
let final_upvar_tys = self.final_upvar_tys(id); let final_upvar_tys = self.final_upvar_tys(closure_node_id);
debug!("analyze_closure: id={:?} closure_substs={:?} final_upvar_tys={:?}", debug!("analyze_closure: id={:?} closure_substs={:?} final_upvar_tys={:?}",
id, closure_substs, final_upvar_tys); closure_node_id, closure_substs, final_upvar_tys);
for (upvar_ty, final_upvar_ty) in for (upvar_ty, final_upvar_ty) in
closure_substs.upvar_tys(def_id, self.tcx).zip(final_upvar_tys) closure_substs.upvar_tys(def_id, self.tcx).zip(final_upvar_tys)
{ {
@ -195,7 +206,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// If we are also inferred the closure kind here, // If we are also inferred the closure kind here,
// process any deferred resolutions. // process any deferred resolutions.
if infer_kind { if infer_kind {
let closure_def_id = self.tcx.hir.local_def_id(id);
let deferred_call_resolutions = let deferred_call_resolutions =
self.remove_deferred_call_resolutions(closure_def_id); self.remove_deferred_call_resolutions(closure_def_id);
for deferred_call_resolution in deferred_call_resolutions { for deferred_call_resolution in deferred_call_resolutions {
@ -212,19 +222,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// This may change if abstract return types of some sort are // This may change if abstract return types of some sort are
// implemented. // implemented.
let tcx = self.tcx; let tcx = self.tcx;
let closure_def_index = tcx.hir.local_def_id(closure_id).index;
tcx.with_freevars(closure_id, |freevars| { tcx.with_freevars(closure_id, |freevars| {
freevars.iter().map(|freevar| { freevars.iter().map(|freevar| {
let def_id = freevar.def.def_id(); let var_def_id = freevar.def.def_id();
let var_id = tcx.hir.as_local_node_id(def_id).unwrap(); let var_node_id = tcx.hir.as_local_node_id(var_def_id).unwrap();
let freevar_ty = self.node_ty(tcx.hir.node_to_hir_id(var_id)); let freevar_ty = self.node_ty(tcx.hir.node_to_hir_id(var_node_id));
let upvar_id = ty::UpvarId { let upvar_id = ty::UpvarId {
var_id: var_id, var_id: var_def_id.index,
closure_expr_id: closure_id closure_expr_id: closure_def_index,
}; };
let capture = self.tables.borrow().upvar_capture(upvar_id); let capture = self.tables.borrow().upvar_capture(upvar_id);
debug!("var_id={:?} freevar_ty={:?} capture={:?}", debug!("var_id={:?} freevar_ty={:?} capture={:?}",
var_id, freevar_ty, capture); var_node_id, freevar_ty, capture);
match capture { match capture {
ty::UpvarCapture::ByValue => freevar_ty, ty::UpvarCapture::ByValue => freevar_ty,
@ -242,7 +254,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
struct InferBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { struct InferBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
adjust_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>, adjust_closure_kinds: FxHashMap<DefIndex, (ty::ClosureKind, Option<(Span, ast::Name)>)>,
adjust_upvar_captures: ty::UpvarCaptureMap<'tcx>, adjust_upvar_captures: ty::UpvarCaptureMap<'tcx>,
} }
@ -281,7 +293,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
self.adjust_closure_kind(upvar_id.closure_expr_id, self.adjust_closure_kind(upvar_id.closure_expr_id,
ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce,
guarantor.span, guarantor.span,
tcx.hir.name(upvar_id.var_id)); var_name(tcx, upvar_id.var_id));
self.adjust_upvar_captures.insert(upvar_id, ty::UpvarCapture::ByValue); self.adjust_upvar_captures.insert(upvar_id, ty::UpvarCapture::ByValue);
} }
@ -295,7 +307,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
self.adjust_closure_kind(upvar_id.closure_expr_id, self.adjust_closure_kind(upvar_id.closure_expr_id,
ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce,
guarantor.span, guarantor.span,
tcx.hir.name(upvar_id.var_id)); var_name(tcx, upvar_id.var_id));
} }
mc::NoteNone => { mc::NoteNone => {
} }
@ -400,7 +412,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
self.adjust_closure_kind(upvar_id.closure_expr_id, self.adjust_closure_kind(upvar_id.closure_expr_id,
ty::ClosureKind::FnMut, ty::ClosureKind::FnMut,
cmt.span, cmt.span,
tcx.hir.name(upvar_id.var_id)); var_name(tcx, upvar_id.var_id));
true true
} }
@ -411,7 +423,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
self.adjust_closure_kind(upvar_id.closure_expr_id, self.adjust_closure_kind(upvar_id.closure_expr_id,
ty::ClosureKind::FnMut, ty::ClosureKind::FnMut,
cmt.span, cmt.span,
tcx.hir.name(upvar_id.var_id)); var_name(tcx, upvar_id.var_id));
true true
} }
@ -460,23 +472,23 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
} }
fn adjust_closure_kind(&mut self, fn adjust_closure_kind(&mut self,
closure_id: ast::NodeId, closure_id: DefIndex,
new_kind: ty::ClosureKind, new_kind: ty::ClosureKind,
upvar_span: Span, upvar_span: Span,
var_name: ast::Name) { var_name: ast::Name) {
debug!("adjust_closure_kind(closure_id={}, new_kind={:?}, upvar_span={:?}, var_name={})", debug!("adjust_closure_kind(closure_id={:?}, new_kind={:?}, upvar_span={:?}, var_name={})",
closure_id, new_kind, upvar_span, var_name); closure_id, new_kind, upvar_span, var_name);
let closure_kind = self.adjust_closure_kinds.get(&closure_id).cloned() let closure_kind = self.adjust_closure_kinds.get(&closure_id).cloned()
.or_else(|| { .or_else(|| {
let closure_id = self.fcx.tcx.hir.node_to_hir_id(closure_id); let closure_id = self.fcx.tcx.hir.def_index_to_hir_id(closure_id);
let fcx_tables = self.fcx.tables.borrow(); let fcx_tables = self.fcx.tables.borrow();
fcx_tables.validate_hir_id(closure_id); fcx_tables.validate_hir_id(closure_id);
fcx_tables.closure_kinds.get(&closure_id.local_id).cloned() fcx_tables.closure_kinds.get(&closure_id.local_id).cloned()
}); });
if let Some((existing_kind, _)) = closure_kind { if let Some((existing_kind, _)) = closure_kind {
debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}", debug!("adjust_closure_kind: closure_id={:?}, existing_kind={:?}, new_kind={:?}",
closure_id, existing_kind, new_kind); closure_id, existing_kind, new_kind);
match (existing_kind, new_kind) { match (existing_kind, new_kind) {
@ -566,3 +578,8 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> {
self.adjust_upvar_borrow_kind_for_mut(assignee_cmt); self.adjust_upvar_borrow_kind_for_mut(assignee_cmt);
} }
} }
fn var_name(tcx: ty::TyCtxt, var_def_index: DefIndex) -> ast::Name {
let var_node_id = tcx.hir.def_index_to_node_id(var_def_index);
tcx.hir.name(var_node_id)
}

View file

@ -14,7 +14,7 @@
use check::FnCtxt; use check::FnCtxt;
use rustc::hir; use rustc::hir;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::{DefId, DefIndex};
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::infer::{InferCtxt}; use rustc::infer::{InferCtxt};
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
@ -401,6 +401,13 @@ impl Locatable for ast::NodeId {
fn to_span(&self, tcx: &TyCtxt) -> Span { tcx.hir.span(*self) } fn to_span(&self, tcx: &TyCtxt) -> Span { tcx.hir.span(*self) }
} }
impl Locatable for DefIndex {
fn to_span(&self, tcx: &TyCtxt) -> Span {
let node_id = tcx.hir.def_index_to_node_id(*self);
tcx.hir.span(node_id)
}
}
impl Locatable for hir::HirId { impl Locatable for hir::HirId {
fn to_span(&self, tcx: &TyCtxt) -> Span { fn to_span(&self, tcx: &TyCtxt) -> Span {
let node_id = tcx.hir.definitions().find_node_for_hir_id(*self); let node_id = tcx.hir.definitions().find_node_for_hir_id(*self);