Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc: remove Res::Upvar. #61276

Merged
merged 11 commits into from
Jun 2, 2019
9 changes: 9 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1183,6 +1183,11 @@ dependencies = [
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "indexmap"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this data structure have any "classic" name?
Search by "IndexMap" only leads to the Rust version.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really know (for the record, this crate used to be called ordermap). cc @bluss

version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "installer"
version = "0.0.0"
Expand Down Expand Up @@ -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)",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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)",
]

Expand Down Expand Up @@ -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"
Expand Down
1 change: 1 addition & 0 deletions src/librustc/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ macro_rules! arena_types {
>,
[few] crate_variances: rustc::ty::CrateVariancesMap<'tcx>,
[few] inferred_outlives_crate: rustc::ty::CratePredicatesMap<'tcx>,
[] upvars: rustc_data_structures::fx::FxIndexMap<rustc::hir::HirId, rustc::hir::Upvar>,
], $tcx);
)
}
Expand Down
10 changes: 0 additions & 10 deletions src/librustc/hir/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,6 @@ pub enum Res<Id = hir::HirId> {
// Value namespace
SelfCtor(DefId /* impl */), // `DefId` refers to the impl
Local(Id),
Upvar(Id, // `HirId` of closed over local
usize, // index in the `upvars` list of the closure
ast::NodeId), // expr node that creates the closure

// Macro namespace
NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]`
Expand Down Expand Up @@ -347,7 +344,6 @@ impl<Id> Res<Id> {
Res::Def(_, id) => Some(id),

Res::Local(..) |
Res::Upvar(..) |
Res::PrimTy(..) |
Res::SelfTy(..) |
Res::SelfCtor(..) |
Expand All @@ -374,7 +370,6 @@ impl<Id> Res<Id> {
Res::SelfCtor(..) => "self constructor",
Res::PrimTy(..) => "builtin type",
Res::Local(..) => "local variable",
Res::Upvar(..) => "closure capture",
Res::SelfTy(..) => "self type",
Res::ToolMod => "tool module",
Res::NonMacroAttr(attr_kind) => attr_kind.descr(),
Expand All @@ -397,11 +392,6 @@ impl<Id> Res<Id> {
Res::SelfCtor(id) => Res::SelfCtor(id),
Res::PrimTy(id) => Res::PrimTy(id),
Res::Local(id) => Res::Local(map(id)),
Res::Upvar(id, index, closure) => Res::Upvar(
map(id),
index,
closure
),
Res::SelfTy(a, b) => Res::SelfTy(a, b),
Res::ToolMod => Res::ToolMod,
Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
Expand Down
18 changes: 10 additions & 8 deletions src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::util::common::time;

use std::io;
use std::result::Result::Err;
use crate::ty::TyCtxt;
use crate::ty::query::Providers;

pub mod blocks;
mod collector;
Expand Down Expand Up @@ -1450,11 +1450,13 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
}
}

pub fn def_kind(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option<DefKind> {
if let Some(node_id) = tcx.hir().as_local_node_id(def_id) {
tcx.hir().def_kind(node_id)
} else {
bug!("Calling local def_kind query provider for upstream DefId: {:?}",
def_id)
}
pub fn provide(providers: &mut Providers<'_>) {
providers.def_kind = |tcx, def_id| {
if let Some(node_id) = tcx.hir().as_local_node_id(def_id) {
tcx.hir().def_kind(node_id)
} else {
bug!("Calling local def_kind query provider for upstream DefId: {:?}",
def_id)
}
};
}
29 changes: 4 additions & 25 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pub mod lowering;
pub mod map;
pub mod pat_util;
pub mod print;
pub mod upvars;

/// Uniquely identifies a node in the HIR of the current crate. It is
/// composed of the `owner`, which is the `DefIndex` of the directly enclosing
Expand Down Expand Up @@ -1408,7 +1409,6 @@ impl Expr {
ExprKind::Path(QPath::Resolved(_, ref path)) => {
match path.res {
Res::Local(..)
| Res::Upvar(..)
| Res::Def(DefKind::Static, _)
| Res::Err => true,
_ => false,
Expand Down Expand Up @@ -2493,32 +2493,11 @@ 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 res: Res<Id>,

pub struct Upvar {
// First span where it is accessed (there can be multiple).
pub span: Span
}

impl<Id: fmt::Debug + Copy> Upvar<Id> {
pub fn map_id<R>(self, map: impl FnMut(Id) -> R) -> Upvar<R> {
Upvar {
res: self.res.map_id(map),
span: self.span,
}
}

pub fn var_id(&self) -> Id {
match self.res {
Res::Local(id) | Res::Upvar(id, ..) => id,
_ => bug!("Upvar::var_id: bad res ({:?})", self.res)
}
}
}

pub type UpvarMap = NodeMap<Vec<Upvar<ast::NodeId>>>;

pub type CaptureModeMap = NodeMap<CaptureClause>;

// The TraitCandidate's import_ids is empty if the trait is defined in the same module, and
Expand All @@ -2537,10 +2516,10 @@ pub type TraitMap = NodeMap<Vec<TraitCandidate>>;
// imported.
pub type GlobMap = NodeMap<FxHashSet<Name>>;


pub fn provide(providers: &mut Providers<'_>) {
check_attr::provide(providers);
providers.def_kind = map::def_kind;
map::provide(providers);
upvars::provide(providers);
}

#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
Expand Down
104 changes: 104 additions & 0 deletions src/librustc/hir/upvars.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//! Upvar (closure capture) collection from cross-body HIR uses of `Res::Local`s.

use crate::hir::{self, HirId};
use crate::hir::def::Res;
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
use crate::ty::TyCtxt;
use crate::ty::query::Providers;
use syntax_pos::Span;
use rustc_data_structures::fx::{FxIndexMap, FxHashSet};

pub fn provide(providers: &mut Providers<'_>) {
providers.upvars = |tcx, def_id| {
if !tcx.is_closure(def_id) {
return None;
}

let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
let body = tcx.hir().body(tcx.hir().maybe_body_owned_by(node_id)?);

let mut local_collector = LocalCollector::default();
local_collector.visit_body(body);

let mut capture_collector = CaptureCollector {
tcx,
locals: &local_collector.locals,
upvars: FxIndexMap::default(),
};
capture_collector.visit_body(body);

if !capture_collector.upvars.is_empty() {
Some(tcx.arena.alloc(capture_collector.upvars))
} else {
None
}
};
}

#[derive(Default)]
struct LocalCollector {
// FIXME(eddyb) perhaps use `ItemLocalId` instead?
locals: FxHashSet<HirId>,
}

impl Visitor<'tcx> for LocalCollector {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::None
}

fn visit_pat(&mut self, pat: &'tcx hir::Pat) {
if let hir::PatKind::Binding(_, hir_id, ..) = pat.node {
self.locals.insert(hir_id);
}
intravisit::walk_pat(self, pat);
}
}

struct CaptureCollector<'a, 'tcx> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
locals: &'a FxHashSet<HirId>,
upvars: FxIndexMap<HirId, hir::Upvar>,
}

impl CaptureCollector<'_, '_> {
fn visit_local_use(&mut self, var_id: HirId, span: Span) {
if !self.locals.contains(&var_id) {
self.upvars.entry(var_id).or_insert(hir::Upvar { span });
}
}
}

impl Visitor<'tcx> for CaptureCollector<'a, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::None
}

fn visit_path(&mut self, path: &'tcx hir::Path, _: hir::HirId) {
if let Res::Local(var_id) = path.res {
self.visit_local_use(var_id, path.span);
}

intravisit::walk_path(self, path);
}

fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
if let hir::ExprKind::Closure(..) = expr.node {
let closure_def_id = self.tcx.hir().local_def_id_from_hir_id(expr.hir_id);
if let Some(upvars) = self.tcx.upvars(closure_def_id) {
// Every capture of a closure expression is a local in scope,
// that is moved/copied/borrowed into the closure value, and
// for this analysis they are like any other access to a local.
//
// E.g. in `|b| |c| (a, b, c)`, the upvars of the inner closure
// are `a` and `b`, and while `a` is not directly used in the
// outer closure, it needs to be an upvar there too, so that
// the inner closure can take it (from the outer closure's env).
for (&var_id, upvar) in upvars {
self.visit_local_use(var_id, upvar.span);
eddyb marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

intravisit::walk_expr(self, expr);
}
}
2 changes: 1 addition & 1 deletion src/librustc/middle/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
}
_ if self.in_pat => {},
Res::PrimTy(..) | Res::SelfTy(..) | Res::SelfCtor(..) |
Res::Local(..) | Res::Upvar(..) => {}
Res::Local(..) => {}
Res::Def(DefKind::Ctor(CtorOf::Variant, ..), ctor_def_id) => {
let variant_id = self.tcx.parent(ctor_def_id).unwrap();
let enum_id = self.tcx.parent(variant_id).unwrap();
Expand Down
26 changes: 16 additions & 10 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> {
/// See also `with_infer`, which is used *during* typeck.
pub fn new(delegate: &'a mut (dyn Delegate<'tcx>+'a),
tcx: TyCtxt<'a, 'tcx, 'tcx>,
body_owner: DefId,
param_env: ty::ParamEnv<'tcx>,
region_scope_tree: &'a region::ScopeTree,
tables: &'a ty::TypeckTables<'tcx>,
Expand All @@ -276,6 +277,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> {
{
ExprUseVisitor {
mc: mc::MemCategorizationContext::new(tcx,
body_owner,
region_scope_tree,
tables,
rvalue_promotable_map),
Expand All @@ -288,13 +290,19 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> {
impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
pub fn with_infer(delegate: &'a mut (dyn Delegate<'tcx>+'a),
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
body_owner: DefId,
param_env: ty::ParamEnv<'tcx>,
region_scope_tree: &'a region::ScopeTree,
tables: &'a ty::TypeckTables<'tcx>)
-> Self
{
ExprUseVisitor {
mc: mc::MemCategorizationContext::with_infer(infcx, region_scope_tree, tables),
mc: mc::MemCategorizationContext::with_infer(
infcx,
body_owner,
region_scope_tree,
tables,
),
delegate,
param_env,
}
Expand Down Expand Up @@ -924,16 +932,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() {
let var_hir_id = upvar.var_id();
for (&var_id, upvar) in upvars.iter() {
let upvar_id = ty::UpvarId {
var_path: ty::UpvarPath { hir_id: var_hir_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,
upvar));
var_id));
match upvar_capture {
ty::UpvarCapture::ByValue => {
let mode = copy_or_move(&self.mc,
Expand All @@ -958,13 +965,12 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
fn cat_captured_var(&mut self,
closure_hir_id: hir::HirId,
closure_span: Span,
upvar: &hir::Upvar)
var_id: hir::HirId)
-> mc::McResult<mc::cmt_<'tcx>> {
// Create the cmt for the variable being borrowed, from the
// caller's perspective
let var_hir_id = upvar.var_id();
let var_ty = self.mc.node_ty(var_hir_id)?;
self.mc.cat_res(closure_hir_id, closure_span, var_ty, upvar.res)
// perspective of the creator (parent) of the closure.
let var_ty = self.mc.node_ty(var_id)?;
self.mc.cat_res(closure_hir_id, closure_span, var_ty, Res::Local(var_id))
}
}

Expand Down
Loading