提交 15d8e8fb 编写于 作者: B Blitzerr

[Cleanup] This is the first in the series of removals of with_freevars usage.

Currently, there are many places in rustc, where we use
with_freevars to iterate over freevars of a closure. The
problem with this is the argument to with_freevars is a
NodeId and this will get in the way of our eventual goal
of solving for issue (#53488), sub-issue (#56905)
上级 7853b780
...@@ -422,7 +422,7 @@ pub struct TypeckTables<'tcx> { ...@@ -422,7 +422,7 @@ pub struct TypeckTables<'tcx> {
/// The upvarID contains the HIR node ID and it also contains the full path /// The upvarID contains the HIR node ID and it also contains the full path
/// leading to the member of the struct or tuple that is used instead of the /// leading to the member of the struct or tuple that is used instead of the
/// entire variable. /// entire variable.
pub upvar_list: ty::UpvarListMap<'tcx>, pub upvar_list: ty::UpvarListMap,
} }
impl<'tcx> TypeckTables<'tcx> { impl<'tcx> TypeckTables<'tcx> {
......
...@@ -808,7 +808,7 @@ pub struct UpvarBorrow<'tcx> { ...@@ -808,7 +808,7 @@ pub struct UpvarBorrow<'tcx> {
pub region: ty::Region<'tcx>, pub region: ty::Region<'tcx>,
} }
pub type UpvarListMap<'tcx> = FxHashMap<ast::NodeId, Vec<UpvarId>>; pub type UpvarListMap = FxHashMap<DefId, Vec<UpvarId>>;
pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>; pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
use hair::{LintLevel, BindingMode, PatternKind}; use hair::{LintLevel, BindingMode, PatternKind};
use rustc::hir; use rustc::hir;
use rustc::hir::Node; use rustc::hir::Node;
use rustc::hir::def_id::{DefId, LocalDefId}; use rustc::hir::def_id::DefId;
use rustc::middle::region; use rustc::middle::region;
use rustc::mir::*; use rustc::mir::*;
use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::mir::visit::{MutVisitor, TyContext};
...@@ -640,47 +640,49 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, ...@@ -640,47 +640,49 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
let arguments: Vec<_> = arguments.collect(); let arguments: Vec<_> = arguments.collect();
let tcx = hir.tcx(); let tcx = hir.tcx();
let span = tcx.hir().span(fn_id); let tcx_hir = tcx.hir();
let span = tcx_hir.span(fn_id);
// hir.tables().upvar_list[fn_id]. let hir_tables = hir.tables();
// Gather the upvars of a closure, if any. let fn_def_id = tcx_hir.local_def_id(fn_id);
let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| {
freevars.iter().map(|fv| {
let var_id = fv.var_id();
let var_hir_id = tcx.hir().node_to_hir_id(var_id);
let closure_expr_id = tcx.hir().local_def_id(fn_id);
let capture = hir.tables().upvar_capture(ty::UpvarId {
var_path: ty::UpvarPath {hir_id: var_hir_id},
closure_expr_id: LocalDefId::from_def_id(closure_expr_id),
});
let by_ref = match capture {
ty::UpvarCapture::ByValue => false,
ty::UpvarCapture::ByRef(..) => true
};
let mut decl = UpvarDecl {
debug_name: keywords::Invalid.name(),
var_hir_id: ClearCrossCrate::Set(var_hir_id),
by_ref,
mutability: Mutability::Not,
};
if let Some(Node::Binding(pat)) = tcx.hir().find(var_id) {
if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
decl.debug_name = ident.name;
if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) { // Gather the upvars of a closure, if any.
if bm == ty::BindByValue(hir::MutMutable) { let upvar_decls: Vec<_> = match hir_tables.upvar_list.get(&fn_def_id) {
decl.mutability = Mutability::Mut; Some(upvars) => upvars
.iter()
.map(|upvar_id| {
let var_hir_id = upvar_id.var_path.hir_id;
let var_node_id = tcx_hir.hir_to_node_id(var_hir_id);
let capture = hir_tables.upvar_capture(*upvar_id);
let by_ref = match capture {
ty::UpvarCapture::ByValue => false,
ty::UpvarCapture::ByRef(..) => true,
};
let mut decl = UpvarDecl {
debug_name: keywords::Invalid.name(),
var_hir_id: ClearCrossCrate::Set(var_hir_id),
by_ref,
mutability: Mutability::Not,
};
if let Some(Node::Binding(pat)) = tcx_hir.find(var_node_id) {
if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
decl.debug_name = ident.name;
if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) {
if bm == ty::BindByValue(hir::MutMutable) {
decl.mutability = Mutability::Mut;
} else {
decl.mutability = Mutability::Not;
}
} else { } else {
decl.mutability = Mutability::Not; tcx.sess.delay_span_bug(pat.span, "missing binding mode");
} }
} else {
tcx.sess.delay_span_bug(pat.span, "missing binding mode");
} }
} }
} decl
decl })
}).collect() .collect(),
}); _ => vec![],
};
let mut builder = Builder::new(hir, let mut builder = Builder::new(hir,
span, span,
...@@ -690,7 +692,6 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, ...@@ -690,7 +692,6 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
return_ty_span, return_ty_span,
upvar_decls); upvar_decls);
let fn_def_id = tcx.hir().local_def_id(fn_id);
let call_site_scope = region::Scope { let call_site_scope = region::Scope {
id: body.value.hir_id.local_id, id: body.value.hir_id.local_id,
data: region::ScopeData::CallSite data: region::ScopeData::CallSite
...@@ -733,7 +734,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, ...@@ -733,7 +734,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
// RustCall pseudo-ABI untuples the last argument. // RustCall pseudo-ABI untuples the last argument.
spread_arg = Some(Local::new(arguments.len())); spread_arg = Some(Local::new(arguments.len()));
} }
let closure_expr_id = tcx.hir().local_def_id(fn_id); let closure_expr_id = tcx_hir.local_def_id(fn_id);
info!("fn_id {:?} has attrs {:?}", closure_expr_id, info!("fn_id {:?} has attrs {:?}", closure_expr_id,
tcx.get_attrs(closure_expr_id)); tcx.get_attrs(closure_expr_id));
......
...@@ -156,10 +156,12 @@ fn analyze_closure( ...@@ -156,10 +156,12 @@ fn analyze_closure(
// Add the vector of freevars to the map keyed with the closure id. // Add the vector of freevars to the map keyed with the closure id.
// This gives us an easier access to them without having to call // This gives us an easier access to them without having to call
// with_freevars again.. // with_freevars again..
self.tables if !freevar_list.is_empty() {
.borrow_mut() self.tables
.upvar_list .borrow_mut()
.insert(closure_node_id, freevar_list); .upvar_list
.insert(closure_def_id, freevar_list);
}
}); });
let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id()); let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id());
......
...@@ -20,6 +20,15 @@ ...@@ -20,6 +20,15 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Entry point // Entry point
/// During type inference, partially inferred types are
/// represented using Type variables (ty::Infer). These don't appear in
/// the final TypeckTables since all of the types should have been
/// inferred once typeck_tables_of is done.
/// When type inference is running however, having to update the typeck
/// tables every time a new type is inferred would be unreasonably slow,
/// so instead all of the replacement happens at the end in
/// resolve_type_vars_in_body, which creates a new TypeTables which
/// doesn't contain any inference types.
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::TypeckTables<'gcx> { pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::TypeckTables<'gcx> {
...@@ -35,7 +44,8 @@ pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::Type ...@@ -35,7 +44,8 @@ pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::Type
wbcx.visit_node_id(arg.pat.span, arg.hir_id); wbcx.visit_node_id(arg.pat.span, arg.hir_id);
} }
wbcx.visit_body(body); wbcx.visit_body(body);
wbcx.visit_upvar_borrow_map(); wbcx.visit_upvar_capture_map();
wbcx.visit_upvar_list_map();
wbcx.visit_closures(); wbcx.visit_closures();
wbcx.visit_liberated_fn_sigs(); wbcx.visit_liberated_fn_sigs();
wbcx.visit_fru_field_types(); wbcx.visit_fru_field_types();
...@@ -291,7 +301,7 @@ fn visit_ty(&mut self, hir_ty: &'gcx hir::Ty) { ...@@ -291,7 +301,7 @@ fn visit_ty(&mut self, hir_ty: &'gcx hir::Ty) {
} }
impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
fn visit_upvar_borrow_map(&mut self) { fn visit_upvar_capture_map(&mut self) {
for (upvar_id, upvar_capture) in self.fcx.tables.borrow().upvar_capture_map.iter() { for (upvar_id, upvar_capture) in self.fcx.tables.borrow().upvar_capture_map.iter() {
let new_upvar_capture = match *upvar_capture { let new_upvar_capture = match *upvar_capture {
ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue, ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue,
...@@ -314,6 +324,21 @@ fn visit_upvar_borrow_map(&mut self) { ...@@ -314,6 +324,21 @@ fn visit_upvar_borrow_map(&mut self) {
} }
} }
/// Runs through the function context's upvar list map and adds the same to
/// the TypeckTables. upvarlist is a hashmap of the list of upvars referred
/// to in a closure..
fn visit_upvar_list_map(&mut self) {
for (closure_def_id, upvar_list) in self.fcx.tables.borrow().upvar_list.iter() {
debug!(
"UpvarIDs captured by closure {:?} are: {:?}",
closure_def_id, upvar_list
);
self.tables
.upvar_list
.insert(*closure_def_id, upvar_list.to_vec());
}
}
fn visit_closures(&mut self) { fn visit_closures(&mut self) {
let fcx_tables = self.fcx.tables.borrow(); let fcx_tables = self.fcx.tables.borrow();
debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册