mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
rustc: use indexmap instead of a plain vector for upvars.
This commit is contained in:
parent
9fe0052e54
commit
961fe5479f
@ -1183,6 +1183,11 @@ dependencies = [
|
||||
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "installer"
|
||||
version = "0.0.0"
|
||||
@ -2719,6 +2724,7 @@ dependencies = [
|
||||
"cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"graphviz 0.0.0",
|
||||
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2970,6 +2976,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"arena 0.0.0",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
@ -3236,6 +3243,7 @@ dependencies = [
|
||||
name = "serialize"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -4199,6 +4207,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum if_chain 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c3360c7b59e5ffa2653671fb74b4741a5d343c03f331c0a4aeda42b5c2b0ec7d"
|
||||
"checksum ignore 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8dc57fa12805f367736a38541ac1a9fc6a52812a0ca959b1d4d4b640a89eb002"
|
||||
"checksum im-rc 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0197597d095c0d11107975d3175173f810ee572c2501ff4de64f4f3f119806"
|
||||
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
|
||||
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
|
||||
"checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053"
|
||||
"checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450"
|
||||
|
@ -30,6 +30,7 @@ use syntax::util::parser::ExprPrecedence;
|
||||
use crate::ty::AdtKind;
|
||||
use crate::ty::query::Providers;
|
||||
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
|
||||
use rustc_data_structures::thin_vec::ThinVec;
|
||||
use rustc_macros::HashStable;
|
||||
@ -2493,10 +2494,7 @@ impl ForeignItemKind {
|
||||
|
||||
/// A variable captured by a closure.
|
||||
#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub struct Upvar<Id = HirId> {
|
||||
/// The variable being captured.
|
||||
pub var_id: Id,
|
||||
|
||||
pub struct Upvar {
|
||||
/// Whether this is not a direct capture (comes from parent closure).
|
||||
pub has_parent: bool,
|
||||
|
||||
@ -2504,17 +2502,7 @@ pub struct Upvar<Id = HirId> {
|
||||
pub span: Span
|
||||
}
|
||||
|
||||
impl<Id: fmt::Debug + Copy> Upvar<Id> {
|
||||
pub fn map_id<R>(self, map: impl FnOnce(Id) -> R) -> Upvar<R> {
|
||||
Upvar {
|
||||
var_id: map(self.var_id),
|
||||
has_parent: self.has_parent,
|
||||
span: self.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type UpvarMap = NodeMap<Vec<Upvar<ast::NodeId>>>;
|
||||
pub type UpvarMap = NodeMap<FxIndexMap<ast::NodeId, Upvar>>;
|
||||
|
||||
pub type CaptureModeMap = NodeMap<CaptureClause>;
|
||||
|
||||
|
@ -924,14 +924,15 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
|
||||
let closure_def_id = self.tcx().hir().local_def_id_from_hir_id(closure_expr.hir_id);
|
||||
if let Some(upvars) = self.tcx().upvars(closure_def_id) {
|
||||
for upvar in upvars.iter() {
|
||||
for (&var_id, upvar) in upvars.iter() {
|
||||
let upvar_id = ty::UpvarId {
|
||||
var_path: ty::UpvarPath { hir_id: upvar.var_id },
|
||||
var_path: ty::UpvarPath { hir_id: var_id },
|
||||
closure_expr_id: closure_def_id.to_local(),
|
||||
};
|
||||
let upvar_capture = self.mc.tables.upvar_capture(upvar_id);
|
||||
let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.hir_id,
|
||||
fn_decl_span,
|
||||
var_id,
|
||||
upvar));
|
||||
match upvar_capture {
|
||||
ty::UpvarCapture::ByValue => {
|
||||
@ -957,6 +958,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
fn cat_captured_var(&mut self,
|
||||
closure_hir_id: hir::HirId,
|
||||
closure_span: Span,
|
||||
var_id: hir::HirId,
|
||||
upvar: &hir::Upvar)
|
||||
-> mc::McResult<mc::cmt_<'tcx>> {
|
||||
// Create the cmt for the variable being borrowed, from the
|
||||
@ -965,11 +967,11 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
let closure_def_id = self.tcx().hir().local_def_id_from_hir_id(closure_hir_id);
|
||||
let parent_def_id = self.tcx().parent(closure_def_id).unwrap();
|
||||
assert!(self.tcx().is_closure(parent_def_id));
|
||||
let var_nid = self.tcx().hir().hir_to_node_id(upvar.var_id);
|
||||
let var_nid = self.tcx().hir().hir_to_node_id(var_id);
|
||||
self.mc.cat_upvar(closure_hir_id, closure_span, var_nid, parent_def_id)
|
||||
} else {
|
||||
let var_ty = self.mc.node_ty(upvar.var_id)?;
|
||||
self.mc.cat_res(closure_hir_id, closure_span, var_ty, Res::Local(upvar.var_id))
|
||||
let var_ty = self.mc.node_ty(var_id)?;
|
||||
self.mc.cat_res(closure_hir_id, closure_span, var_ty, Res::Local(var_id))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -485,10 +485,10 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
|
||||
let mut call_caps = Vec::new();
|
||||
let closure_def_id = ir.tcx.hir().local_def_id_from_hir_id(expr.hir_id);
|
||||
if let Some(upvars) = ir.tcx.upvars(closure_def_id) {
|
||||
call_caps.extend(upvars.iter().filter_map(|upvar| {
|
||||
call_caps.extend(upvars.iter().filter_map(|(&var_id, upvar)| {
|
||||
if !upvar.has_parent {
|
||||
let upvar_ln = ir.add_live_node(UpvarNode(upvar.span));
|
||||
Some(CaptureInfo { ln: upvar_ln, var_hid: upvar.var_id })
|
||||
Some(CaptureInfo { ln: upvar_ln, var_hid: var_id })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -2562,8 +2562,8 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
||||
let mut struct_fmt = fmt.debug_struct(&name);
|
||||
|
||||
if let Some(upvars) = tcx.upvars(def_id) {
|
||||
for (upvar, place) in upvars.iter().zip(places) {
|
||||
let var_name = tcx.hir().name_by_hir_id(upvar.var_id);
|
||||
for (&var_id, place) in upvars.keys().zip(places) {
|
||||
let var_name = tcx.hir().name_by_hir_id(var_id);
|
||||
struct_fmt.field(&var_name.as_str(), place);
|
||||
}
|
||||
}
|
||||
@ -2581,8 +2581,8 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
||||
let mut struct_fmt = fmt.debug_struct(&name);
|
||||
|
||||
if let Some(upvars) = tcx.upvars(def_id) {
|
||||
for (upvar, place) in upvars.iter().zip(places) {
|
||||
let var_name = tcx.hir().name_by_hir_id(upvar.var_id);
|
||||
for (&var_id, place) in upvars.keys().zip(places) {
|
||||
let var_name = tcx.hir().name_by_hir_id(var_id);
|
||||
struct_fmt.field(&var_name.as_str(), place);
|
||||
}
|
||||
}
|
||||
|
@ -826,7 +826,7 @@ rustc_queries! {
|
||||
desc { "generating a postorder list of CrateNums" }
|
||||
}
|
||||
|
||||
query upvars(_: DefId) -> Option<&'tcx [hir::Upvar]> {
|
||||
query upvars(_: DefId) -> Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>> {
|
||||
eval_always
|
||||
}
|
||||
query maybe_unused_trait_import(_: DefId) -> bool {
|
||||
|
@ -54,6 +54,7 @@ use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
|
||||
StableHasher, StableHasherResult,
|
||||
StableVec};
|
||||
use arena::SyncDroplessArena;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use rustc_data_structures::sync::{Lrc, Lock, WorkerLocal};
|
||||
use std::any::Any;
|
||||
@ -1065,7 +1066,7 @@ pub struct GlobalCtxt<'tcx> {
|
||||
// Records the captured variables referenced by every closure
|
||||
// expression. Do not track deps for this, just recompute it from
|
||||
// scratch every time.
|
||||
upvars: FxHashMap<DefId, Vec<hir::Upvar>>,
|
||||
upvars: FxHashMap<DefId, FxIndexMap<hir::HirId, hir::Upvar>>,
|
||||
|
||||
maybe_unused_trait_imports: FxHashSet<DefId>,
|
||||
maybe_unused_extern_crates: Vec<(DefId, Span)>,
|
||||
@ -1297,11 +1298,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}).collect();
|
||||
(k, exports)
|
||||
}).collect(),
|
||||
upvars: resolutions.upvars.into_iter().map(|(k, v)| {
|
||||
let vars: Vec<_> = v.into_iter().map(|e| {
|
||||
e.map_id(|id| hir.node_to_hir_id(id))
|
||||
upvars: resolutions.upvars.into_iter().map(|(k, upvars)| {
|
||||
let upvars: FxIndexMap<_, _> = upvars.into_iter().map(|(var_id, upvar)| {
|
||||
(hir.node_to_hir_id(var_id), upvar)
|
||||
}).collect();
|
||||
(hir.local_def_id(k), vars)
|
||||
(hir.local_def_id(k), upvars)
|
||||
}).collect(),
|
||||
maybe_unused_trait_imports:
|
||||
resolutions.maybe_unused_trait_imports
|
||||
@ -3023,7 +3024,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
|
||||
assert_eq!(id, LOCAL_CRATE);
|
||||
tcx.arena.alloc(middle::lang_items::collect(tcx))
|
||||
};
|
||||
providers.upvars = |tcx, id| tcx.gcx.upvars.get(&id).map(|v| &v[..]);
|
||||
providers.upvars = |tcx, id| tcx.gcx.upvars.get(&id);
|
||||
providers.maybe_unused_trait_import = |tcx, id| {
|
||||
tcx.maybe_unused_trait_imports.contains(&id)
|
||||
};
|
||||
|
@ -51,6 +51,7 @@ use syntax::symbol::{kw, sym, Symbol, LocalInternedString, InternedString};
|
||||
use syntax_pos::Span;
|
||||
|
||||
use smallvec;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
|
||||
HashStable};
|
||||
@ -808,7 +809,7 @@ pub struct UpvarBorrow<'tcx> {
|
||||
pub region: ty::Region<'tcx>,
|
||||
}
|
||||
|
||||
pub type UpvarListMap = FxHashMap<DefId, Vec<UpvarId>>;
|
||||
pub type UpvarListMap = FxHashMap<DefId, FxIndexMap<hir::HirId, UpvarId>>;
|
||||
pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -585,16 +585,16 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
|
||||
if let Some(hir_id) = self.tcx().hir().as_local_hir_id(did) {
|
||||
p!(write("@{:?}", self.tcx().hir().span_by_hir_id(hir_id)));
|
||||
let mut sep = " ";
|
||||
for (upvar, upvar_ty) in self.tcx().upvars(did)
|
||||
for (&var_id, upvar_ty) in self.tcx().upvars(did)
|
||||
.as_ref()
|
||||
.map_or(&[][..], |v| &v[..])
|
||||
.iter()
|
||||
.flat_map(|v| v.keys())
|
||||
.zip(upvar_tys)
|
||||
{
|
||||
p!(
|
||||
write("{}{}:",
|
||||
sep,
|
||||
self.tcx().hir().name_by_hir_id(upvar.var_id)),
|
||||
self.tcx().hir().name_by_hir_id(var_id)),
|
||||
print(upvar_ty));
|
||||
sep = ", ";
|
||||
}
|
||||
@ -628,16 +628,16 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
|
||||
p!(write("@{:?}", self.tcx().hir().span_by_hir_id(hir_id)));
|
||||
}
|
||||
let mut sep = " ";
|
||||
for (upvar, upvar_ty) in self.tcx().upvars(did)
|
||||
for (&var_id, upvar_ty) in self.tcx().upvars(did)
|
||||
.as_ref()
|
||||
.map_or(&[][..], |v| &v[..])
|
||||
.iter()
|
||||
.flat_map(|v| v.keys())
|
||||
.zip(upvar_tys)
|
||||
{
|
||||
p!(
|
||||
write("{}{}:",
|
||||
sep,
|
||||
self.tcx().hir().name_by_hir_id(upvar.var_id)),
|
||||
self.tcx().hir().name_by_hir_id(var_id)),
|
||||
print(upvar_ty));
|
||||
sep = ", ";
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ use crate::util::profiling::ProfileCategory::*;
|
||||
use rustc_data_structures::svh::Svh;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::stable_hasher::StableVec;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
|
@ -11,6 +11,7 @@ crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
ena = "0.13"
|
||||
indexmap = "1"
|
||||
log = "0.4"
|
||||
jobserver_crate = { version = "0.1.13", package = "jobserver" }
|
||||
lazy_static = "1"
|
||||
|
@ -1 +1,6 @@
|
||||
use std::hash::BuildHasherDefault;
|
||||
|
||||
pub use rustc_hash::{FxHasher, FxHashMap, FxHashSet};
|
||||
|
||||
pub type FxIndexMap<K, V> = indexmap::IndexMap<K, V, BuildHasherDefault<FxHasher>>;
|
||||
pub type FxIndexSet<V> = indexmap::IndexSet<V, BuildHasherDefault<FxHasher>>;
|
||||
|
@ -323,6 +323,37 @@ impl<T: HashStable<CTX>, CTX> HashStable<CTX> for Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, R, CTX> HashStable<CTX> for indexmap::IndexMap<K, V, R>
|
||||
where K: HashStable<CTX> + Eq + Hash,
|
||||
V: HashStable<CTX>,
|
||||
R: BuildHasher,
|
||||
{
|
||||
#[inline]
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
ctx: &mut CTX,
|
||||
hasher: &mut StableHasher<W>) {
|
||||
self.len().hash_stable(ctx, hasher);
|
||||
for kv in self {
|
||||
kv.hash_stable(ctx, hasher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, R, CTX> HashStable<CTX> for indexmap::IndexSet<K, R>
|
||||
where K: HashStable<CTX> + Eq + Hash,
|
||||
R: BuildHasher,
|
||||
{
|
||||
#[inline]
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
ctx: &mut CTX,
|
||||
hasher: &mut StableHasher<W>) {
|
||||
self.len().hash_stable(ctx, hasher);
|
||||
for key in self {
|
||||
key.hash_stable(ctx, hasher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, CTX> HashStable<CTX> for SmallVec<[A; 1]> where A: HashStable<CTX> {
|
||||
#[inline]
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
|
@ -348,9 +348,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
// `tcx.upvars(def_id)` returns an `Option`, which is `None` in case
|
||||
// the closure comes from another crate. But in that case we wouldn't
|
||||
// be borrowck'ing it, so we can just unwrap:
|
||||
let upvar = self.infcx.tcx.upvars(def_id).unwrap()[field.index()];
|
||||
let (&var_id, _) = self.infcx.tcx.upvars(def_id).unwrap()
|
||||
.get_index(field.index()).unwrap();
|
||||
|
||||
self.infcx.tcx.hir().name_by_hir_id(upvar.var_id).to_string()
|
||||
self.infcx.tcx.hir().name_by_hir_id(var_id).to_string()
|
||||
}
|
||||
_ => {
|
||||
// Might need a revision when the fields in trait RFC is implemented
|
||||
@ -645,12 +646,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
if let hir::ExprKind::Closure(
|
||||
.., args_span, _
|
||||
) = expr {
|
||||
for (v, place) in self.infcx.tcx.upvars(def_id)?.iter().zip(places) {
|
||||
for (upvar, place) in self.infcx.tcx.upvars(def_id)?.values().zip(places) {
|
||||
match place {
|
||||
Operand::Copy(place) |
|
||||
Operand::Move(place) if target_place == place => {
|
||||
debug!("closure_span: found captured local {:?}", place);
|
||||
return Some((*args_span, v.span));
|
||||
return Some((*args_span, upvar.span));
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
||||
.upvar_list
|
||||
.get(&def_id)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flat_map(|v| v.values())
|
||||
.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);
|
||||
|
@ -651,10 +651,9 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
.get(&fn_def_id)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(|upvar_id| {
|
||||
let var_hir_id = upvar_id.var_path.hir_id;
|
||||
.map(|(&var_hir_id, &upvar_id)| {
|
||||
let var_node_id = tcx_hir.hir_to_node_id(var_hir_id);
|
||||
let capture = hir_tables.upvar_capture(*upvar_id);
|
||||
let capture = hir_tables.upvar_capture(upvar_id);
|
||||
let by_ref = match capture {
|
||||
ty::UpvarCapture::ByValue => false,
|
||||
ty::UpvarCapture::ByRef(..) => true,
|
||||
|
@ -515,7 +515,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
let upvars = cx.tcx.upvars(def_id).iter()
|
||||
.flat_map(|upvars| upvars.iter())
|
||||
.zip(substs.upvar_tys(def_id, cx.tcx))
|
||||
.map(|(upvar, ty)| capture_upvar(cx, expr, upvar, ty))
|
||||
.map(|((&var_hir_id, upvar), ty)| capture_upvar(cx, expr, var_hir_id, upvar, ty))
|
||||
.collect();
|
||||
ExprKind::Closure {
|
||||
closure_id: def_id,
|
||||
@ -964,7 +964,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
Res::Upvar(var_hir_id, closure_node_id) => {
|
||||
let closure_def_id = cx.tcx.hir().local_def_id(closure_node_id);
|
||||
assert_eq!(cx.body_owner, closure_def_id);
|
||||
assert!(cx.upvar_indices.contains_key(&var_hir_id));
|
||||
assert!(cx.tables().upvar_list[&cx.body_owner].contains_key(&var_hir_id));
|
||||
|
||||
convert_var(cx, expr, var_hir_id)
|
||||
}
|
||||
@ -978,7 +978,8 @@ fn convert_var(
|
||||
expr: &'tcx hir::Expr,
|
||||
var_hir_id: hir::HirId,
|
||||
) -> ExprKind<'tcx> {
|
||||
let upvar_index = cx.upvar_indices.get(&var_hir_id).cloned();
|
||||
let upvar_index = cx.tables().upvar_list.get(&cx.body_owner)
|
||||
.and_then(|upvars| upvars.get_full(&var_hir_id).map(|(i, _, _)| i));
|
||||
|
||||
debug!("convert_var({:?}): upvar_index={:?}, body_owner={:?}",
|
||||
var_hir_id, upvar_index, cx.body_owner);
|
||||
@ -1186,26 +1187,31 @@ fn overloaded_place<'a, 'gcx, 'tcx>(
|
||||
|
||||
fn capture_upvar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
closure_expr: &'tcx hir::Expr,
|
||||
var_hir_id: hir::HirId,
|
||||
upvar: &hir::Upvar,
|
||||
upvar_ty: Ty<'tcx>)
|
||||
-> ExprRef<'tcx> {
|
||||
let upvar_id = ty::UpvarId {
|
||||
var_path: ty::UpvarPath { hir_id: upvar.var_id },
|
||||
var_path: ty::UpvarPath { hir_id: var_hir_id },
|
||||
closure_expr_id: cx.tcx.hir().local_def_id_from_hir_id(closure_expr.hir_id).to_local(),
|
||||
};
|
||||
let upvar_capture = cx.tables().upvar_capture(upvar_id);
|
||||
let temp_lifetime = cx.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id);
|
||||
let var_ty = cx.tables().node_type(upvar.var_id);
|
||||
let var_ty = cx.tables().node_type(var_hir_id);
|
||||
if upvar.has_parent {
|
||||
let closure_def_id = upvar_id.closure_expr_id.to_def_id();
|
||||
assert_eq!(cx.body_owner, cx.tcx.parent(closure_def_id).unwrap());
|
||||
}
|
||||
assert_eq!(upvar.has_parent, cx.upvar_indices.contains_key(&upvar.var_id));
|
||||
assert_eq!(
|
||||
upvar.has_parent,
|
||||
cx.tables().upvar_list.get(&cx.body_owner)
|
||||
.map_or(false, |upvars| upvars.contains_key(&var_hir_id)),
|
||||
);
|
||||
let captured_var = Expr {
|
||||
temp_lifetime,
|
||||
ty: var_ty,
|
||||
span: closure_expr.span,
|
||||
kind: convert_var(cx, closure_expr, upvar.var_id),
|
||||
kind: convert_var(cx, closure_expr, var_hir_id),
|
||||
};
|
||||
match upvar_capture {
|
||||
ty::UpvarCapture::ByValue => captured_var.to_ref(),
|
||||
|
@ -5,7 +5,6 @@
|
||||
use crate::hair::*;
|
||||
use crate::hair::util::UserAnnotatedTyHelpers;
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::Node;
|
||||
@ -50,9 +49,6 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||
|
||||
/// See field with the same name on `mir::Body`.
|
||||
control_flow_destroyed: Vec<(Span, String)>,
|
||||
|
||||
/// Reverse map, from upvar variable `HirId`s to their indices.
|
||||
upvar_indices: FxHashMap<hir::HirId, usize>,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
@ -83,14 +79,6 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
// Constants always need overflow checks.
|
||||
check_overflow |= constness == hir::Constness::Const;
|
||||
|
||||
// Compute reverse mapping, of uvpars to their indices.
|
||||
let mut upvar_indices = FxHashMap::default();
|
||||
if let Some(upvars) = tables.upvar_list.get(&src_def_id) {
|
||||
upvar_indices.extend(
|
||||
upvars.iter().enumerate().map(|(i, upvar_id)| (upvar_id.var_path.hir_id, i)),
|
||||
);
|
||||
}
|
||||
|
||||
Cx {
|
||||
tcx,
|
||||
infcx,
|
||||
@ -104,7 +92,6 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
body_owner_kind,
|
||||
check_overflow,
|
||||
control_flow_destroyed: Vec::new(),
|
||||
upvar_indices,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,8 +174,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> ValidityVisitor<'rt, 'a, '
|
||||
if let Some(upvars) = tables.upvar_list.get(&def_id) {
|
||||
// Sometimes the index is beyond the number of upvars (seen
|
||||
// for a generator).
|
||||
if let Some(upvar_id) = upvars.get(field) {
|
||||
let var_hir_id = upvar_id.var_path.hir_id;
|
||||
if let Some((&var_hir_id, _)) = upvars.get_index(field) {
|
||||
let var_node_id = self.ecx.tcx.hir().hir_to_node_id(var_hir_id);
|
||||
if let hir::Node::Binding(pat) = self.ecx.tcx.hir().get(var_node_id) {
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
|
||||
|
@ -12,6 +12,7 @@ test = false
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.0"
|
||||
indexmap = "1"
|
||||
log = "0.4"
|
||||
syntax = { path = "../libsyntax" }
|
||||
rustc = { path = "../librustc" }
|
||||
|
@ -1669,7 +1669,6 @@ pub struct Resolver<'a> {
|
||||
label_res_map: NodeMap<NodeId>,
|
||||
|
||||
pub upvars: UpvarMap,
|
||||
upvars_seen: NodeMap<NodeSet>,
|
||||
pub export_map: ExportMap<NodeId>,
|
||||
pub trait_map: TraitMap,
|
||||
|
||||
@ -2033,7 +2032,6 @@ impl<'a> Resolver<'a> {
|
||||
import_res_map: Default::default(),
|
||||
label_res_map: Default::default(),
|
||||
upvars: Default::default(),
|
||||
upvars_seen: Default::default(),
|
||||
export_map: FxHashMap::default(),
|
||||
trait_map: Default::default(),
|
||||
module_map,
|
||||
@ -4055,26 +4053,18 @@ impl<'a> Resolver<'a> {
|
||||
Res::Upvar(..) => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
let seen = self.upvars_seen
|
||||
.entry(function_id)
|
||||
.or_default();
|
||||
if seen.contains(&var_id) {
|
||||
res = Res::Upvar(var_id, function_id);
|
||||
continue;
|
||||
}
|
||||
let vec = self.upvars
|
||||
.entry(function_id)
|
||||
.or_default();
|
||||
res = Res::Upvar(var_id, function_id);
|
||||
|
||||
if record_used {
|
||||
vec.push(Upvar {
|
||||
var_id,
|
||||
has_parent,
|
||||
span,
|
||||
});
|
||||
seen.insert(var_id);
|
||||
match self.upvars.entry(function_id).or_default().entry(var_id) {
|
||||
indexmap::map::Entry::Occupied(_) => continue,
|
||||
indexmap::map::Entry::Vacant(entry) => {
|
||||
if record_used {
|
||||
entry.insert(Upvar {
|
||||
has_parent,
|
||||
span,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemRibKind | FnItemRibKind | AssocItemRibKind => {
|
||||
|
@ -41,6 +41,7 @@ use rustc::hir::def_id::LocalDefId;
|
||||
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||
use rustc::infer::UpvarRegion;
|
||||
use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
|
||||
@ -122,18 +123,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
};
|
||||
|
||||
if let Some(upvars) = self.tcx.upvars(closure_def_id) {
|
||||
let mut upvar_list: Vec<ty::UpvarId> = Vec::with_capacity(upvars.len());
|
||||
for upvar in upvars.iter() {
|
||||
let mut upvar_list: FxIndexMap<hir::HirId, ty::UpvarId> =
|
||||
FxIndexMap::with_capacity_and_hasher(upvars.len(), Default::default());
|
||||
for (&var_hir_id, _) in upvars.iter() {
|
||||
let upvar_id = ty::UpvarId {
|
||||
var_path: ty::UpvarPath {
|
||||
hir_id: upvar.var_id,
|
||||
hir_id: var_hir_id,
|
||||
},
|
||||
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.
|
||||
upvar_list.push(upvar_id);
|
||||
upvar_list.insert(var_hir_id, upvar_id);
|
||||
|
||||
let capture_kind = match capture_clause {
|
||||
hir::CaptureByValue => ty::UpvarCapture::ByValue,
|
||||
@ -249,17 +251,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
tcx.upvars(closure_def_id).iter().flat_map(|upvars| {
|
||||
upvars
|
||||
.iter()
|
||||
.map(|upvar| {
|
||||
let upvar_ty = self.node_ty(upvar.var_id);
|
||||
.map(|(&var_hir_id, _)| {
|
||||
let upvar_ty = self.node_ty(var_hir_id);
|
||||
let upvar_id = ty::UpvarId {
|
||||
var_path: ty::UpvarPath { hir_id: upvar.var_id },
|
||||
var_path: ty::UpvarPath { hir_id: var_hir_id },
|
||||
closure_expr_id: LocalDefId::from_def_id(closure_def_id),
|
||||
};
|
||||
let capture = self.tables.borrow().upvar_capture(upvar_id);
|
||||
|
||||
debug!(
|
||||
"var_id={:?} upvar_ty={:?} capture={:?}",
|
||||
upvar.var_id, upvar_ty, capture
|
||||
var_hir_id, upvar_ty, capture
|
||||
);
|
||||
|
||||
match capture {
|
||||
|
@ -54,7 +54,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
wbcx.visit_body(body);
|
||||
wbcx.visit_upvar_capture_map();
|
||||
wbcx.visit_upvar_list_map();
|
||||
wbcx.visit_closures();
|
||||
wbcx.visit_liberated_fn_sigs();
|
||||
wbcx.visit_fru_field_types();
|
||||
@ -74,6 +73,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
);
|
||||
wbcx.tables.used_trait_imports = used_trait_imports;
|
||||
|
||||
wbcx.tables.upvar_list = mem::replace(
|
||||
&mut self.tables.borrow_mut().upvar_list,
|
||||
Default::default(),
|
||||
);
|
||||
|
||||
wbcx.tables.tainted_by_errors = self.is_tainted_by_errors();
|
||||
|
||||
debug!(
|
||||
@ -343,21 +347,6 @@ 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);
|
||||
|
@ -10,4 +10,5 @@ path = "lib.rs"
|
||||
crate-type = ["dylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
indexmap = "1"
|
||||
smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
|
||||
|
@ -217,6 +217,75 @@ impl<T, S> Decodable for HashSet<T, S>
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, S> Encodable for indexmap::IndexMap<K, V, S>
|
||||
where K: Encodable + Hash + Eq,
|
||||
V: Encodable,
|
||||
S: BuildHasher,
|
||||
{
|
||||
fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
|
||||
e.emit_map(self.len(), |e| {
|
||||
let mut i = 0;
|
||||
for (key, val) in self {
|
||||
e.emit_map_elt_key(i, |e| key.encode(e))?;
|
||||
e.emit_map_elt_val(i, |e| val.encode(e))?;
|
||||
i += 1;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, S> Decodable for indexmap::IndexMap<K, V, S>
|
||||
where K: Decodable + Hash + Eq,
|
||||
V: Decodable,
|
||||
S: BuildHasher + Default,
|
||||
{
|
||||
fn decode<D: Decoder>(d: &mut D) -> Result<indexmap::IndexMap<K, V, S>, D::Error> {
|
||||
d.read_map(|d, len| {
|
||||
let state = Default::default();
|
||||
let mut map = indexmap::IndexMap::with_capacity_and_hasher(len, state);
|
||||
for i in 0..len {
|
||||
let key = d.read_map_elt_key(i, |d| Decodable::decode(d))?;
|
||||
let val = d.read_map_elt_val(i, |d| Decodable::decode(d))?;
|
||||
map.insert(key, val);
|
||||
}
|
||||
Ok(map)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> Encodable for indexmap::IndexSet<T, S>
|
||||
where T: Encodable + Hash + Eq,
|
||||
S: BuildHasher,
|
||||
{
|
||||
fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
|
||||
s.emit_seq(self.len(), |s| {
|
||||
let mut i = 0;
|
||||
for e in self {
|
||||
s.emit_seq_elt(i, |s| e.encode(s))?;
|
||||
i += 1;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> Decodable for indexmap::IndexSet<T, S>
|
||||
where T: Decodable + Hash + Eq,
|
||||
S: BuildHasher + Default,
|
||||
{
|
||||
fn decode<D: Decoder>(d: &mut D) -> Result<indexmap::IndexSet<T, S>, D::Error> {
|
||||
d.read_seq(|d, len| {
|
||||
let state = Default::default();
|
||||
let mut set = indexmap::IndexSet::with_capacity_and_hasher(len, state);
|
||||
for i in 0..len {
|
||||
set.insert(d.read_seq_elt(i, |d| Decodable::decode(d))?);
|
||||
}
|
||||
Ok(set)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Encodable> Encodable for Rc<[T]> {
|
||||
fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
|
||||
s.emit_seq(self.len(), |s| {
|
||||
|
@ -92,6 +92,7 @@ const WHITELIST: &[Crate<'_>] = &[
|
||||
Crate("fuchsia-zircon-sys"),
|
||||
Crate("getopts"),
|
||||
Crate("humantime"),
|
||||
Crate("indexmap"),
|
||||
Crate("itertools"),
|
||||
Crate("jobserver"),
|
||||
Crate("kernel32-sys"),
|
||||
|
Loading…
Reference in New Issue
Block a user