From 47db51eecee943dc2af1adc467d1ff47685e6d09 Mon Sep 17 00:00:00 2001 From: Blitzerr Date: Sun, 16 Dec 2018 17:01:57 -0800 Subject: [PATCH 1/5] Issue 56905 Adding a map to TypeckTables to get the list of all the Upvars given a closureID. This is help us get rid of the recurring pattern in the codebase of iterating over the free vars using with_freevars. --- src/librustc/ty/context.rs | 10 ++++++++++ src/librustc/ty/mod.rs | 2 ++ src/librustc_typeck/check/upvar.rs | 18 ++++++++++++------ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index c0ba4329ae05c..aebf71791bc60 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -417,6 +417,12 @@ pub struct TypeckTables<'tcx> { /// All the existential types that are restricted to concrete types /// by this function pub concrete_existential_types: FxHashMap>, + + /// Given the closure ID this map provides the list of UpvarIDs used by it. + /// 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 + /// entire variable. + pub upvar_list: ty::UpvarListMap<'tcx>, } impl<'tcx> TypeckTables<'tcx> { @@ -441,6 +447,7 @@ impl<'tcx> TypeckTables<'tcx> { tainted_by_errors: false, free_region_map: Default::default(), concrete_existential_types: Default::default(), + upvar_list: Default::default(), } } @@ -741,6 +748,8 @@ impl<'a, 'gcx> HashStable> for TypeckTables<'gcx> { tainted_by_errors, ref free_region_map, ref concrete_existential_types, + ref upvar_list, + } = *self; hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { @@ -783,6 +792,7 @@ impl<'a, 'gcx> HashStable> for TypeckTables<'gcx> { tainted_by_errors.hash_stable(hcx, hasher); free_region_map.hash_stable(hcx, hasher); concrete_existential_types.hash_stable(hcx, hasher); + upvar_list.hash_stable(hcx, hasher); }) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index a2c96e7cf9f66..f770f2bf7b125 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -589,6 +589,8 @@ impl<'a, 'gcx> HashStable> for ty::TyS<'gcx> { pub type Ty<'tcx> = &'tcx TyS<'tcx>; +pub type UpvarListMap<'tcx> = FxHashMap>; + impl<'tcx> serialize::UseSpecializedEncodable for Ty<'tcx> {} impl<'tcx> serialize::UseSpecializedDecodable for Ty<'tcx> {} diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 86165d50b27e4..c37e0e262cf5f 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -122,14 +122,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; self.tcx.with_freevars(closure_node_id, |freevars| { + let mut freevar_list: Vec = Vec::new(); for freevar in freevars { let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { - hir_id : self.tcx.hir().node_to_hir_id(freevar.var_id()), + hir_id: self.tcx.hir().node_to_hir_id(freevar.var_id()), }, closure_expr_id: LocalDefId::from_def_id(closure_def_id), }; debug!("seed upvar_id {:?}", upvar_id); + freevar_list.push(upvar_id); let capture_kind = match capture_clause { hir::CaptureByValue => ty::UpvarCapture::ByValue, @@ -149,6 +151,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .upvar_capture_map .insert(upvar_id, capture_kind); } + self.tables + .borrow_mut() + .upvar_list + .insert(closure_def_id, freevar_list); }); let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id()); @@ -166,7 +172,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.param_env, region_scope_tree, &self.tables.borrow(), - ).consume_body(body); + ) + .consume_body(body); if let Some(closure_substs) = infer_kind { // Unify the (as yet unbound) type variable in the closure @@ -240,9 +247,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let var_hir_id = tcx.hir().node_to_hir_id(var_node_id); let freevar_ty = self.node_ty(var_hir_id); let upvar_id = ty::UpvarId { - var_path: ty::UpvarPath { - hir_id: var_hir_id, - }, + var_path: ty::UpvarPath { hir_id: var_hir_id }, closure_expr_id: LocalDefId::from_def_id(closure_def_index), }; let capture = self.tables.borrow().upvar_capture(upvar_id); @@ -262,7 +267,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }, ), } - }).collect() + }) + .collect() }) } } From 410b52958da4434c2638da15e6c6c9a7ef665761 Mon Sep 17 00:00:00 2001 From: Blitzerr Date: Tue, 18 Dec 2018 20:54:35 -0800 Subject: [PATCH 2/5] Creating the vector using with_capacity to avoid re-allocation later on (#56905) --- src/librustc_typeck/check/upvar.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index c37e0e262cf5f..2a50f63b7925b 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -122,7 +122,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; self.tcx.with_freevars(closure_node_id, |freevars| { - let mut freevar_list: Vec = Vec::new(); + let mut freevar_list: Vec = Vec::with_capacity(freevars.len()); for freevar in freevars { let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { @@ -131,6 +131,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { closure_expr_id: LocalDefId::from_def_id(closure_def_id), }; debug!("seed upvar_id {:?}", upvar_id); + // Adding the upvar Id to the list of Upvars, which will be added + // to the map for the closure at the end of the for loop. freevar_list.push(upvar_id); let capture_kind = match capture_clause { @@ -151,6 +153,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .upvar_capture_map .insert(upvar_id, capture_kind); } + // 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 + // with_freevars again.. self.tables .borrow_mut() .upvar_list From 7853b780fc678e670362690ddeb8648d552db0bf Mon Sep 17 00:00:00 2001 From: Blitzerr Date: Fri, 21 Dec 2018 20:00:11 -0800 Subject: [PATCH 3/5] Some more refactoring. Change the key of UpvarListMap from DefId to ast::NodeId --- src/librustc/ty/mod.rs | 3 +-- src/librustc_mir/build/mod.rs | 1 + src/librustc_typeck/check/upvar.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index f770f2bf7b125..8afe0241ac863 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -589,8 +589,6 @@ impl<'a, 'gcx> HashStable> for ty::TyS<'gcx> { pub type Ty<'tcx> = &'tcx TyS<'tcx>; -pub type UpvarListMap<'tcx> = FxHashMap>; - impl<'tcx> serialize::UseSpecializedEncodable for Ty<'tcx> {} impl<'tcx> serialize::UseSpecializedDecodable for Ty<'tcx> {} @@ -810,6 +808,7 @@ pub struct UpvarBorrow<'tcx> { pub region: ty::Region<'tcx>, } +pub type UpvarListMap<'tcx> = FxHashMap>; pub type UpvarCaptureMap<'tcx> = FxHashMap>; #[derive(Copy, Clone)] diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 727b769cf4d44..4b0907f808364 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -642,6 +642,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let tcx = hir.tcx(); let span = tcx.hir().span(fn_id); + // hir.tables().upvar_list[fn_id]. // Gather the upvars of a closure, if any. let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| { freevars.iter().map(|fv| { diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 2a50f63b7925b..24d13d9c2acfa 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -159,7 +159,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.tables .borrow_mut() .upvar_list - .insert(closure_def_id, freevar_list); + .insert(closure_node_id, freevar_list); }); let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id()); From 15d8e8fb2b5ae3c1493b82077a2c5d3252926227 Mon Sep 17 00:00:00 2001 From: Blitzerr Date: Sat, 22 Dec 2018 15:06:14 -0800 Subject: [PATCH 4/5] [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) --- src/librustc/ty/context.rs | 2 +- src/librustc/ty/mod.rs | 2 +- src/librustc_mir/build/mod.rs | 77 +++++++++++++------------- src/librustc_typeck/check/upvar.rs | 10 ++-- src/librustc_typeck/check/writeback.rs | 29 +++++++++- 5 files changed, 74 insertions(+), 46 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index aebf71791bc60..8d4b8aae8b176 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -422,7 +422,7 @@ pub struct TypeckTables<'tcx> { /// 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 /// entire variable. - pub upvar_list: ty::UpvarListMap<'tcx>, + pub upvar_list: ty::UpvarListMap, } impl<'tcx> TypeckTables<'tcx> { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8afe0241ac863..cfd99948e4370 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -808,7 +808,7 @@ pub struct UpvarBorrow<'tcx> { pub region: ty::Region<'tcx>, } -pub type UpvarListMap<'tcx> = FxHashMap>; +pub type UpvarListMap = FxHashMap>; pub type UpvarCaptureMap<'tcx> = FxHashMap>; #[derive(Copy, Clone)] diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 4b0907f808364..b1a377591e310 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -4,7 +4,7 @@ use hair::cx::Cx; use hair::{LintLevel, BindingMode, PatternKind}; use rustc::hir; use rustc::hir::Node; -use rustc::hir::def_id::{DefId, LocalDefId}; +use rustc::hir::def_id::DefId; use rustc::middle::region; use rustc::mir::*; use rustc::mir::visit::{MutVisitor, TyContext}; @@ -640,47 +640,49 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let arguments: Vec<_> = arguments.collect(); 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]. - // Gather the upvars of a closure, if any. - 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; + let hir_tables = hir.tables(); + let fn_def_id = tcx_hir.local_def_id(fn_id); - if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) { - if bm == ty::BindByValue(hir::MutMutable) { - decl.mutability = Mutability::Mut; + // Gather the upvars of a closure, if any. + let upvar_decls: Vec<_> = match hir_tables.upvar_list.get(&fn_def_id) { + 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 { - 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 - }).collect() - }); + decl + }) + .collect(), + _ => vec![], + }; let mut builder = Builder::new(hir, span, @@ -690,7 +692,6 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, return_ty_span, upvar_decls); - let fn_def_id = tcx.hir().local_def_id(fn_id); let call_site_scope = region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite @@ -733,7 +734,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, // RustCall pseudo-ABI untuples the last argument. 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, tcx.get_attrs(closure_expr_id)); diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 24d13d9c2acfa..ffd7c2114e5ab 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -156,10 +156,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // 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 // with_freevars again.. - self.tables - .borrow_mut() - .upvar_list - .insert(closure_node_id, freevar_list); + if !freevar_list.is_empty() { + self.tables + .borrow_mut() + .upvar_list + .insert(closure_def_id, freevar_list); + } }); let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id()); diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 38de936a027ff..8499a492bccec 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -20,6 +20,15 @@ use syntax_pos::Span; /////////////////////////////////////////////////////////////////////////// // 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> { 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> { wbcx.visit_node_id(arg.pat.span, arg.hir_id); } wbcx.visit_body(body); - wbcx.visit_upvar_borrow_map(); + wbcx.visit_upvar_capture_map(); + wbcx.visit_upvar_list_map(); wbcx.visit_closures(); wbcx.visit_liberated_fn_sigs(); wbcx.visit_fru_field_types(); @@ -291,7 +301,7 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for 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() { let new_upvar_capture = match *upvar_capture { ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue, @@ -314,6 +324,21 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } } + /// 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) { let fcx_tables = self.fcx.tables.borrow(); debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); From 69e491815d927b3206c8acf88fbdbed8521e5955 Mon Sep 17 00:00:00 2001 From: Blitzerr Date: Tue, 8 Jan 2019 19:13:50 -0800 Subject: [PATCH 5/5] addressing Niko's comments --- src/librustc_mir/build/mod.rs | 68 ++++++++++++++------------ src/librustc_typeck/check/writeback.rs | 18 +++---- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index b1a377591e310..65ae111fbc0fc 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -647,42 +647,46 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let fn_def_id = tcx_hir.local_def_id(fn_id); // Gather the upvars of a closure, if any. - let upvar_decls: Vec<_> = match hir_tables.upvar_list.get(&fn_def_id) { - 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; - } + // In analyze_closure() in upvar.rs we gathered a list of upvars used by a + // closure and we stored in a map called upvar_list in TypeckTables indexed + // with the closure's DefId. Here, we run through that vec of UpvarIds for + // the given closure and use the necessary information to create UpvarDecl. + let upvar_decls: Vec<_> = hir_tables + .upvar_list + .get(&fn_def_id) + .into_iter() + .flatten() + .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 { - tcx.sess.delay_span_bug(pat.span, "missing binding mode"); + decl.mutability = Mutability::Not; } + } else { + tcx.sess.delay_span_bug(pat.span, "missing binding mode"); } } - decl - }) - .collect(), - _ => vec![], - }; + } + decl + }) + .collect(); let mut builder = Builder::new(hir, span, diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 8499a492bccec..c61159eb49481 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -20,16 +20,16 @@ use syntax_pos::Span; /////////////////////////////////////////////////////////////////////////// // 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. +// 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> { pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::TypeckTables<'gcx> { let item_id = self.tcx.hir().body_owner(body.id());