rustc: collect upvars from HIR, instead of during name resolution.

This commit is contained in:
Eduard-Mihai Burtescu 2019-05-28 23:31:01 +03:00
parent 648b4d884d
commit f7a4c9d7b5
12 changed files with 143 additions and 97 deletions

View file

@ -29,7 +29,7 @@ use rustc::hir::def::{
};
use rustc::hir::def::Namespace::*;
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
use rustc::hir::{Upvar, UpvarMap, TraitCandidate, TraitMap, GlobMap};
use rustc::hir::{TraitCandidate, TraitMap, GlobMap};
use rustc::ty::{self, DefIdTree};
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
use rustc::{bug, span_bug};
@ -852,7 +852,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
function_kind: FnKind<'tcx>,
declaration: &'tcx FnDecl,
_: Span,
node_id: NodeId)
_: NodeId)
{
debug!("(resolving function) entering function");
let (rib_kind, asyncness) = match function_kind {
@ -863,17 +863,14 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
FnKind::Closure(_) =>
// Async closures aren't resolved through `visit_fn`-- they're
// processed separately
(ClosureRibKind(node_id), &IsAsync::NotAsync),
(NormalRibKind, &IsAsync::NotAsync),
};
// Create a value rib for the function.
self.ribs[ValueNS].push(Rib::new(rib_kind));
// Create a label rib for the function.
match rib_kind {
ClosureRibKind(_) => {}
_ => self.label_ribs.push(Rib::new(rib_kind)),
}
self.label_ribs.push(Rib::new(rib_kind));
// Add each argument to the rib.
let mut bindings_list = FxHashMap::default();
@ -900,11 +897,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
visit::walk_fn_ret_ty(self, &declaration.output);
// Resolve the function body, potentially inside the body of an async closure
if let IsAsync::Async { closure_id, .. } = asyncness {
let rib_kind = ClosureRibKind(*closure_id);
self.ribs[ValueNS].push(Rib::new(rib_kind));
}
match function_kind {
FnKind::ItemFn(.., body) | FnKind::Method(.., body) => {
if let IsAsync::Async { ref arguments, .. } = asyncness {
@ -927,19 +919,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
}
};
// Leave the body of the async closure
if asyncness.is_async() {
self.ribs[ValueNS].pop();
}
debug!("(resolving function) leaving function");
match rib_kind {
ClosureRibKind(_) => {}
_ => {
self.label_ribs.pop();
}
}
self.label_ribs.pop();
self.ribs[ValueNS].pop();
}
@ -1023,17 +1005,13 @@ enum GenericParameters<'a, 'b> {
RibKind<'a>),
}
/// The rib kind controls the translation of local
/// definitions (`Res::Local`) to upvars (`Res::Upvar`).
/// The rib kind restricts certain accesses,
/// e.g. to a `Res::Local` of an outer item.
#[derive(Copy, Clone, Debug)]
enum RibKind<'a> {
/// No translation needs to be applied.
/// No restriction needs to be applied.
NormalRibKind,
/// We passed through a closure scope at the given `NodeId`.
/// Translate upvars as appropriate.
ClosureRibKind(NodeId /* func id */),
/// We passed through an impl or trait and are now in one of its
/// methods or associated types. Allow references to ty params that impl or trait
/// binds. Disallow any other upvars (including other ty params that are
@ -1673,7 +1651,6 @@ pub struct Resolver<'a> {
/// Resolutions for labels (node IDs of their corresponding blocks or loops).
label_res_map: NodeMap<NodeId>,
pub upvars: UpvarMap,
pub export_map: ExportMap<NodeId>,
pub trait_map: TraitMap,
@ -2036,7 +2013,6 @@ impl<'a> Resolver<'a> {
partial_res_map: Default::default(),
import_res_map: Default::default(),
label_res_map: Default::default(),
upvars: Default::default(),
export_map: FxHashMap::default(),
trait_map: Default::default(),
module_map,
@ -2506,9 +2482,6 @@ impl<'a> Resolver<'a> {
for rib in self.label_ribs.iter().rev() {
match rib.kind {
NormalRibKind => {}
ClosureRibKind(_) => {
span_bug!(ident.span, "rustc_resolve: `ClosureRibKind` in `label_ribs`");
}
// If an invocation of this macro created `ident`, give up on `ident`
// and switch to `ident`'s source from the macro definition.
MacroDefinition(def) => {
@ -4014,7 +3987,7 @@ impl<'a> Resolver<'a> {
diag);
}
// Validate a local resolution (from ribs), potentially recording closure upvars.
// Validate a local resolution (from ribs).
fn validate_res_from_ribs(
&mut self,
ns: Namespace,
@ -4045,7 +4018,7 @@ impl<'a> Resolver<'a> {
}
match res {
Res::Local(var_id) => {
Res::Local(_) => {
use ResolutionError::*;
let mut res_err = None;
@ -4055,12 +4028,6 @@ impl<'a> Resolver<'a> {
ForwardTyParamBanRibKind | TyParamAsConstParamTy => {
// Nothing to do. Continue.
}
ClosureRibKind(function_id) => {
if record_used {
self.upvars.entry(function_id).or_default()
.entry(var_id).or_insert(Upvar { span });
}
}
ItemRibKind | FnItemRibKind | AssocItemRibKind => {
// This was an attempt to access an upvar inside a
// named function item. This is not allowed, so we
@ -4090,7 +4057,7 @@ impl<'a> Resolver<'a> {
Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => {
for rib in ribs {
match rib.kind {
NormalRibKind | AssocItemRibKind | ClosureRibKind(..) |
NormalRibKind | AssocItemRibKind |
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
ConstantItemRibKind | TyParamAsConstParamTy => {
// Nothing to do. Continue.
@ -4470,21 +4437,14 @@ impl<'a> Resolver<'a> {
visit::walk_expr(self, expr);
self.current_type_ascription.pop();
}
// Resolve the body of async exprs inside the async closure to which they desugar
ExprKind::Async(_, async_closure_id, ref block) => {
let rib_kind = ClosureRibKind(async_closure_id);
self.ribs[ValueNS].push(Rib::new(rib_kind));
self.visit_block(&block);
self.ribs[ValueNS].pop();
}
// `async |x| ...` gets desugared to `|x| future_from_generator(|| ...)`, so we need to
// resolve the arguments within the proper scopes so that usages of them inside the
// closure are detected as upvars rather than normal closure arg usages.
ExprKind::Closure(
_, IsAsync::Async { closure_id: inner_closure_id, .. }, _,
_, IsAsync::Async { .. }, _,
ref fn_decl, ref body, _span,
) => {
let rib_kind = ClosureRibKind(expr.id);
let rib_kind = NormalRibKind;
self.ribs[ValueNS].push(Rib::new(rib_kind));
// Resolve arguments:
let mut bindings_list = FxHashMap::default();
@ -4497,14 +4457,11 @@ impl<'a> Resolver<'a> {
// Now resolve the inner closure
{
let rib_kind = ClosureRibKind(inner_closure_id);
self.ribs[ValueNS].push(Rib::new(rib_kind));
// No need to resolve arguments: the inner closure has none.
// Resolve the return type:
visit::walk_fn_ret_ty(self, &fn_decl.output);
// Resolve the body
self.visit_expr(body);
self.ribs[ValueNS].pop();
}
self.ribs[ValueNS].pop();
}