rustc: collect upvars from HIR, instead of during name resolution.
This commit is contained in:
parent
648b4d884d
commit
f7a4c9d7b5
12 changed files with 143 additions and 97 deletions
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue