Skip to content

Commit 15d8e8f

Browse files
committed
[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 (rust-lang#53488), sub-issue (rust-lang#56905)
1 parent 7853b78 commit 15d8e8f

File tree

5 files changed

+74
-46
lines changed

5 files changed

+74
-46
lines changed

src/librustc/ty/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ pub struct TypeckTables<'tcx> {
422422
/// The upvarID contains the HIR node ID and it also contains the full path
423423
/// leading to the member of the struct or tuple that is used instead of the
424424
/// entire variable.
425-
pub upvar_list: ty::UpvarListMap<'tcx>,
425+
pub upvar_list: ty::UpvarListMap,
426426
}
427427

428428
impl<'tcx> TypeckTables<'tcx> {

src/librustc/ty/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,7 @@ pub struct UpvarBorrow<'tcx> {
808808
pub region: ty::Region<'tcx>,
809809
}
810810

811-
pub type UpvarListMap<'tcx> = FxHashMap<ast::NodeId, Vec<UpvarId>>;
811+
pub type UpvarListMap = FxHashMap<DefId, Vec<UpvarId>>;
812812
pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>;
813813

814814
#[derive(Copy, Clone)]

src/librustc_mir/build/mod.rs

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use hair::cx::Cx;
44
use hair::{LintLevel, BindingMode, PatternKind};
55
use rustc::hir;
66
use rustc::hir::Node;
7-
use rustc::hir::def_id::{DefId, LocalDefId};
7+
use rustc::hir::def_id::DefId;
88
use rustc::middle::region;
99
use rustc::mir::*;
1010
use rustc::mir::visit::{MutVisitor, TyContext};
@@ -640,47 +640,49 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
640640
let arguments: Vec<_> = arguments.collect();
641641

642642
let tcx = hir.tcx();
643-
let span = tcx.hir().span(fn_id);
643+
let tcx_hir = tcx.hir();
644+
let span = tcx_hir.span(fn_id);
644645

645-
// hir.tables().upvar_list[fn_id].
646-
// Gather the upvars of a closure, if any.
647-
let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| {
648-
freevars.iter().map(|fv| {
649-
let var_id = fv.var_id();
650-
let var_hir_id = tcx.hir().node_to_hir_id(var_id);
651-
let closure_expr_id = tcx.hir().local_def_id(fn_id);
652-
let capture = hir.tables().upvar_capture(ty::UpvarId {
653-
var_path: ty::UpvarPath {hir_id: var_hir_id},
654-
closure_expr_id: LocalDefId::from_def_id(closure_expr_id),
655-
});
656-
let by_ref = match capture {
657-
ty::UpvarCapture::ByValue => false,
658-
ty::UpvarCapture::ByRef(..) => true
659-
};
660-
let mut decl = UpvarDecl {
661-
debug_name: keywords::Invalid.name(),
662-
var_hir_id: ClearCrossCrate::Set(var_hir_id),
663-
by_ref,
664-
mutability: Mutability::Not,
665-
};
666-
if let Some(Node::Binding(pat)) = tcx.hir().find(var_id) {
667-
if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
668-
decl.debug_name = ident.name;
646+
let hir_tables = hir.tables();
647+
let fn_def_id = tcx_hir.local_def_id(fn_id);
669648

670-
if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) {
671-
if bm == ty::BindByValue(hir::MutMutable) {
672-
decl.mutability = Mutability::Mut;
649+
// Gather the upvars of a closure, if any.
650+
let upvar_decls: Vec<_> = match hir_tables.upvar_list.get(&fn_def_id) {
651+
Some(upvars) => upvars
652+
.iter()
653+
.map(|upvar_id| {
654+
let var_hir_id = upvar_id.var_path.hir_id;
655+
let var_node_id = tcx_hir.hir_to_node_id(var_hir_id);
656+
let capture = hir_tables.upvar_capture(*upvar_id);
657+
let by_ref = match capture {
658+
ty::UpvarCapture::ByValue => false,
659+
ty::UpvarCapture::ByRef(..) => true,
660+
};
661+
let mut decl = UpvarDecl {
662+
debug_name: keywords::Invalid.name(),
663+
var_hir_id: ClearCrossCrate::Set(var_hir_id),
664+
by_ref,
665+
mutability: Mutability::Not,
666+
};
667+
if let Some(Node::Binding(pat)) = tcx_hir.find(var_node_id) {
668+
if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
669+
decl.debug_name = ident.name;
670+
if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) {
671+
if bm == ty::BindByValue(hir::MutMutable) {
672+
decl.mutability = Mutability::Mut;
673+
} else {
674+
decl.mutability = Mutability::Not;
675+
}
673676
} else {
674-
decl.mutability = Mutability::Not;
677+
tcx.sess.delay_span_bug(pat.span, "missing binding mode");
675678
}
676-
} else {
677-
tcx.sess.delay_span_bug(pat.span, "missing binding mode");
678679
}
679680
}
680-
}
681-
decl
682-
}).collect()
683-
});
681+
decl
682+
})
683+
.collect(),
684+
_ => vec![],
685+
};
684686

685687
let mut builder = Builder::new(hir,
686688
span,
@@ -690,7 +692,6 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
690692
return_ty_span,
691693
upvar_decls);
692694

693-
let fn_def_id = tcx.hir().local_def_id(fn_id);
694695
let call_site_scope = region::Scope {
695696
id: body.value.hir_id.local_id,
696697
data: region::ScopeData::CallSite
@@ -733,7 +734,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
733734
// RustCall pseudo-ABI untuples the last argument.
734735
spread_arg = Some(Local::new(arguments.len()));
735736
}
736-
let closure_expr_id = tcx.hir().local_def_id(fn_id);
737+
let closure_expr_id = tcx_hir.local_def_id(fn_id);
737738
info!("fn_id {:?} has attrs {:?}", closure_expr_id,
738739
tcx.get_attrs(closure_expr_id));
739740

src/librustc_typeck/check/upvar.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
156156
// Add the vector of freevars to the map keyed with the closure id.
157157
// This gives us an easier access to them without having to call
158158
// with_freevars again..
159-
self.tables
160-
.borrow_mut()
161-
.upvar_list
162-
.insert(closure_node_id, freevar_list);
159+
if !freevar_list.is_empty() {
160+
self.tables
161+
.borrow_mut()
162+
.upvar_list
163+
.insert(closure_def_id, freevar_list);
164+
}
163165
});
164166

165167
let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id());

src/librustc_typeck/check/writeback.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ use syntax_pos::Span;
2020

2121
///////////////////////////////////////////////////////////////////////////
2222
// Entry point
23+
/// During type inference, partially inferred types are
24+
/// represented using Type variables (ty::Infer). These don't appear in
25+
/// the final TypeckTables since all of the types should have been
26+
/// inferred once typeck_tables_of is done.
27+
/// When type inference is running however, having to update the typeck
28+
/// tables every time a new type is inferred would be unreasonably slow,
29+
/// so instead all of the replacement happens at the end in
30+
/// resolve_type_vars_in_body, which creates a new TypeTables which
31+
/// doesn't contain any inference types.
2332
2433
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
2534
pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::TypeckTables<'gcx> {
@@ -35,7 +44,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3544
wbcx.visit_node_id(arg.pat.span, arg.hir_id);
3645
}
3746
wbcx.visit_body(body);
38-
wbcx.visit_upvar_borrow_map();
47+
wbcx.visit_upvar_capture_map();
48+
wbcx.visit_upvar_list_map();
3949
wbcx.visit_closures();
4050
wbcx.visit_liberated_fn_sigs();
4151
wbcx.visit_fru_field_types();
@@ -291,7 +301,7 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
291301
}
292302

293303
impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
294-
fn visit_upvar_borrow_map(&mut self) {
304+
fn visit_upvar_capture_map(&mut self) {
295305
for (upvar_id, upvar_capture) in self.fcx.tables.borrow().upvar_capture_map.iter() {
296306
let new_upvar_capture = match *upvar_capture {
297307
ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue,
@@ -314,6 +324,21 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
314324
}
315325
}
316326

327+
/// Runs through the function context's upvar list map and adds the same to
328+
/// the TypeckTables. upvarlist is a hashmap of the list of upvars referred
329+
/// to in a closure..
330+
fn visit_upvar_list_map(&mut self) {
331+
for (closure_def_id, upvar_list) in self.fcx.tables.borrow().upvar_list.iter() {
332+
debug!(
333+
"UpvarIDs captured by closure {:?} are: {:?}",
334+
closure_def_id, upvar_list
335+
);
336+
self.tables
337+
.upvar_list
338+
.insert(*closure_def_id, upvar_list.to_vec());
339+
}
340+
}
341+
317342
fn visit_closures(&mut self) {
318343
let fcx_tables = self.fcx.tables.borrow();
319344
debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);

0 commit comments

Comments
 (0)