提交 84284472 编写于 作者: J Jeffrey Seyfried

Move resolution to before lowering

上级 16c8f2cc
......@@ -1438,7 +1438,8 @@ fn make_struct(lctx: &LoweringContext,
let loop_expr = hir::ExprLoop(loop_block,
opt_ident.map(|ident| lower_ident(lctx, ident)));
// add attributes to the outer returned expr node
return expr(lctx, e.span, loop_expr, e.attrs.clone());
let attrs = e.attrs.clone();
return P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs });
}
// Desugar ExprForLoop
......@@ -1515,7 +1516,8 @@ fn make_struct(lctx: &LoweringContext,
let loop_block = block_expr(lctx, match_expr);
let loop_expr = hir::ExprLoop(loop_block,
opt_ident.map(|ident| lower_ident(lctx, ident)));
let loop_expr = expr(lctx, e.span, loop_expr, None);
let loop_expr =
P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: None });
// `mut iter => { ... }`
let iter_arm = {
......
......@@ -195,6 +195,10 @@ pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option<DefId> {
self.opt_def_index(node).map(DefId::local)
}
pub fn local_def_id(&self, node: ast::NodeId) -> DefId {
self.opt_local_def_id(node).unwrap()
}
pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
if def_id.krate == LOCAL_CRATE {
assert!(def_id.index.as_usize() < self.data.len());
......
......@@ -10,7 +10,8 @@
use rustc::dep_graph::DepGraph;
use rustc::hir;
use rustc::hir::map as hir_map;
use rustc::hir::{map as hir_map, FreevarMap, TraitMap};
use rustc::hir::def::DefMap;
use rustc_mir as mir;
use rustc::mir::mir_map::MirMap;
use rustc::session::{Session, CompileResult, compile_result_from_err_count};
......@@ -139,9 +140,32 @@ pub fn compile_input(sess: &Session,
time(sess.time_passes(),
"external crate/lib resolution",
|| LocalCrateReader::new(sess, &cstore, &defs, &expanded_crate, &id)
|| LocalCrateReader::new(sess, &cstore, defs, &expanded_crate, &id)
.read_crates(&dep_graph));
time(sess.time_passes(),
"early lint checks",
|| lint::check_ast_crate(sess, &expanded_crate));
let resolve::CrateMap {
def_map,
freevars,
maybe_unused_trait_imports,
export_map,
trait_map,
glob_map,
} = time(sess.time_passes(), "name resolution", || {
resolve::resolve_crate(sess, &expanded_crate, &defs.borrow(), control.make_glob_map)
});
let analysis = ty::CrateAnalysis {
export_map: export_map,
access_levels: AccessLevels::default(),
reachable: NodeSet(),
name: &id,
glob_map: glob_map,
};
// Lower ast -> hir.
let lcx = LoweringContext::new(sess, Some(&expanded_crate), defs);
let hir_forest = &mut time(sess.time_passes(),
......@@ -185,10 +209,6 @@ pub fn compile_input(sess: &Session,
hir::check_attr::check_crate(sess, &expanded_crate);
});
time(sess.time_passes(),
"early lint checks",
|| lint::check_ast_crate(sess, &expanded_crate));
let opt_crate = if keep_ast(sess) {
Some(&expanded_crate)
} else {
......@@ -200,7 +220,11 @@ pub fn compile_input(sess: &Session,
hir_map,
&arenas,
&id,
control.make_glob_map,
analysis,
def_map,
freevars,
trait_map,
maybe_unused_trait_imports,
|tcx, mir_map, analysis, result| {
{
// Eventually, we will want to track plugins.
......@@ -763,7 +787,11 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
hir_map: hir_map::Map<'tcx>,
arenas: &'tcx ty::CtxtArenas<'tcx>,
name: &str,
make_glob_map: resolve::MakeGlobMap,
mut analysis: ty::CrateAnalysis,
def_map: RefCell<DefMap>,
freevars: FreevarMap,
trait_map: TraitMap,
maybe_unused_trait_imports: NodeSet,
f: F)
-> Result<R, usize>
where F: FnOnce(&TyCtxt<'tcx>, Option<MirMap<'tcx>>, ty::CrateAnalysis, CompileResult) -> R
......@@ -788,25 +816,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
})
})?;
let resolve::CrateMap {
def_map,
freevars,
maybe_unused_trait_imports,
export_map,
trait_map,
glob_map,
} = time(sess.time_passes(),
"name resolution",
|| resolve::resolve_crate(sess, &hir_map, make_glob_map));
let mut analysis = ty::CrateAnalysis {
export_map: export_map,
access_levels: AccessLevels::default(),
reachable: NodeSet(),
name: name,
glob_map: glob_map,
};
let named_region_map = time(time_passes,
"lifetime resolution",
|| middle::resolve_lifetime::krate(sess,
......
......@@ -29,18 +29,15 @@
use syntax::ast::{Name, NodeId};
use syntax::attr::AttrMetaMethods;
use syntax::parse::token::keywords;
use syntax::parse::token::{self, keywords};
use syntax::codemap::{Span, DUMMY_SP};
use rustc::hir;
use rustc::hir::{Block, DeclItem};
use rustc::hir::{ForeignItem, ForeignItemFn, ForeignItemStatic};
use rustc::hir::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
use rustc::hir::{ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaultImpl};
use rustc::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
use rustc::hir::{PathListIdent, PathListMod, StmtDecl};
use rustc::hir::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
use rustc::hir::intravisit::{self, Visitor};
use syntax::ast::{Block, Crate, DeclKind};
use syntax::ast::{ForeignItem, ForeignItemKind, Item, ItemKind};
use syntax::ast::{Mutability, PathListItemKind};
use syntax::ast::{SelfKind, Stmt, StmtKind, TraitItemKind};
use syntax::ast::{Variant, ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
use syntax::visit::{self, Visitor};
trait ToNameBinding<'a> {
fn to_name_binding(self) -> NameBinding<'a>;
......@@ -58,14 +55,14 @@ fn to_name_binding(self) -> NameBinding<'a> {
}
}
impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
impl<'b> Resolver<'b> {
/// Constructs the reduced graph for the entire crate.
pub fn build_reduced_graph(&mut self, krate: &hir::Crate) {
pub fn build_reduced_graph(&mut self, krate: &Crate) {
let mut visitor = BuildReducedGraphVisitor {
parent: self.graph_root,
resolver: self,
};
intravisit::walk_crate(&mut visitor, krate);
visit::walk_crate(&mut visitor, krate);
}
/// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined.
......@@ -85,9 +82,9 @@ fn define<T: ToNameBinding<'b>>(&self, parent: Module<'b>, name: Name, ns: Names
}
fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
fn is_item(statement: &hir::Stmt) -> bool {
if let StmtDecl(ref declaration, _) = statement.node {
if let DeclItem(_) = declaration.node {
fn is_item(statement: &Stmt) -> bool {
if let StmtKind::Decl(ref declaration, _) = statement.node {
if let DeclKind::Item(_) = declaration.node {
return true;
}
}
......@@ -98,7 +95,7 @@ fn is_item(statement: &hir::Stmt) -> bool {
block.stmts.iter().any(is_item)
}
fn sanity_check_import(&self, view_path: &hir::ViewPath, id: NodeId) {
fn sanity_check_import(&self, view_path: &ViewPath, id: NodeId) {
let path = match view_path.node {
ViewPathSimple(_, ref path) |
ViewPathGlob (ref path) |
......@@ -131,13 +128,13 @@ fn sanity_check_import(&self, view_path: &hir::ViewPath, id: NodeId) {
/// Constructs the reduced graph for one item.
fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<'b>) {
let parent = *parent_ref;
let name = item.name;
let name = item.ident.name;
let sp = item.span;
self.current_module = parent;
let vis = self.resolve_visibility(&item.vis);
match item.node {
ItemUse(ref view_path) => {
ItemKind::Use(ref view_path) => {
// Extract and intern the module part of the path. For
// globs and lists, the path is found directly in the AST;
// for simple paths we have to munge the path a little.
......@@ -175,21 +172,20 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<
ResolutionError::SelfImportsOnlyAllowedWithin);
}
let subclass = ImportDirectiveSubclass::single(binding, source_name);
let subclass = ImportDirectiveSubclass::single(binding.name, source_name);
let span = view_path.span;
parent.add_import_directive(module_path, subclass, span, item.id, vis);
self.unresolved_imports += 1;
}
ViewPathList(_, ref source_items) => {
// Make sure there's at most one `mod` import in the list.
let mod_spans = source_items.iter()
.filter_map(|item| {
let mod_spans = source_items.iter().filter_map(|item| {
match item.node {
PathListMod { .. } => Some(item.span),
PathListItemKind::Mod { .. } => Some(item.span),
_ => None,
}
})
.collect::<Vec<Span>>();
}).collect::<Vec<Span>>();
if mod_spans.len() > 1 {
let mut e = resolve_struct_error(self,
mod_spans[0],
......@@ -202,9 +198,9 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<
for source_item in source_items {
let (module_path, name, rename) = match source_item.node {
PathListIdent { name, rename, .. } =>
(module_path.clone(), name, rename.unwrap_or(name)),
PathListMod { rename, .. } => {
PathListItemKind::Ident { name, rename, .. } =>
(module_path.clone(), name.name, rename.unwrap_or(name).name),
PathListItemKind::Mod { rename, .. } => {
let name = match module_path.last() {
Some(name) => *name,
None => {
......@@ -218,7 +214,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<
}
};
let module_path = module_path.split_last().unwrap().1;
let rename = rename.unwrap_or(name);
let rename = rename.map(|i| i.name).unwrap_or(name);
(module_path.to_vec(), name, rename)
}
};
......@@ -237,7 +233,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<
}
}
ItemExternCrate(_) => {
ItemKind::ExternCrate(_) => {
// n.b. we don't need to look at the path option here, because cstore already
// did
if let Some(crate_id) = self.session.cstore.extern_mod_stmt_cnum(item.id) {
......@@ -254,76 +250,77 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<
}
}
ItemMod(..) => {
ItemKind::Mod(..) => {
let parent_link = ModuleParentLink(parent, name);
let def = Def::Mod(self.ast_map.local_def_id(item.id));
let def = Def::Mod(self.definitions.local_def_id(item.id));
let module = self.new_module(parent_link, Some(def), false);
self.define(parent, name, TypeNS, (module, sp, vis));
self.module_map.insert(item.id, module);
*parent_ref = module;
}
ItemForeignMod(..) => {}
ItemKind::ForeignMod(..) => {}
// These items live in the value namespace.
ItemStatic(_, m, _) => {
let mutbl = m == hir::MutMutable;
let def = Def::Static(self.ast_map.local_def_id(item.id), mutbl);
ItemKind::Static(_, m, _) => {
let mutbl = m == Mutability::Mutable;
let def = Def::Static(self.definitions.local_def_id(item.id), mutbl);
self.define(parent, name, ValueNS, (def, sp, vis));
}
ItemConst(_, _) => {
let def = Def::Const(self.ast_map.local_def_id(item.id));
ItemKind::Const(_, _) => {
let def = Def::Const(self.definitions.local_def_id(item.id));
self.define(parent, name, ValueNS, (def, sp, vis));
}
ItemFn(_, _, _, _, _, _) => {
let def = Def::Fn(self.ast_map.local_def_id(item.id));
ItemKind::Fn(_, _, _, _, _, _) => {
let def = Def::Fn(self.definitions.local_def_id(item.id));
self.define(parent, name, ValueNS, (def, sp, vis));
}
// These items live in the type namespace.
ItemTy(..) => {
let def = Def::TyAlias(self.ast_map.local_def_id(item.id));
ItemKind::Ty(..) => {
let def = Def::TyAlias(self.definitions.local_def_id(item.id));
self.define(parent, name, TypeNS, (def, sp, vis));
}
ItemEnum(ref enum_definition, _) => {
ItemKind::Enum(ref enum_definition, _) => {
let parent_link = ModuleParentLink(parent, name);
let def = Def::Enum(self.ast_map.local_def_id(item.id));
let def = Def::Enum(self.definitions.local_def_id(item.id));
let module = self.new_module(parent_link, Some(def), false);
self.define(parent, name, TypeNS, (module, sp, vis));
for variant in &(*enum_definition).variants {
let item_def_id = self.ast_map.local_def_id(item.id);
let item_def_id = self.definitions.local_def_id(item.id);
self.build_reduced_graph_for_variant(variant, item_def_id, module, vis);
}
}
// These items live in both the type and value namespaces.
ItemStruct(ref struct_def, _) => {
ItemKind::Struct(ref struct_def, _) => {
// Define a name in the type namespace.
let def = Def::Struct(self.ast_map.local_def_id(item.id));
let def = Def::Struct(self.definitions.local_def_id(item.id));
self.define(parent, name, TypeNS, (def, sp, vis));
// If this is a newtype or unit-like struct, define a name
// in the value namespace as well
if !struct_def.is_struct() {
let def = Def::Struct(self.ast_map.local_def_id(struct_def.id()));
let def = Def::Struct(self.definitions.local_def_id(struct_def.id()));
self.define(parent, name, ValueNS, (def, sp, vis));
}
// Record the def ID and fields of this struct.
let field_names = struct_def.fields().iter().map(|field| {
let field_names = struct_def.fields().iter().enumerate().map(|(index, field)| {
self.resolve_visibility(&field.vis);
field.name
field.ident.map(|ident| ident.name)
.unwrap_or_else(|| token::intern(&index.to_string()))
}).collect();
let item_def_id = self.ast_map.local_def_id(item.id);
let item_def_id = self.definitions.local_def_id(item.id);
self.structs.insert(item_def_id, field_names);
}
ItemDefaultImpl(_, _) | ItemImpl(..) => {}
ItemKind::DefaultImpl(_, _) | ItemKind::Impl(..) => {}
ItemTrait(_, _, _, ref items) => {
let def_id = self.ast_map.local_def_id(item.id);
ItemKind::Trait(_, _, _, ref items) => {
let def_id = self.definitions.local_def_id(item.id);
// Add all the items within to a new module.
let parent_link = ModuleParentLink(parent, name);
......@@ -333,22 +330,23 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<
// Add the names of all the items to the trait info.
for item in items {
let item_def_id = self.ast_map.local_def_id(item.id);
let item_def_id = self.definitions.local_def_id(item.id);
let mut is_static_method = false;
let (def, ns) = match item.node {
hir::ConstTraitItem(..) => (Def::AssociatedConst(item_def_id), ValueNS),
hir::MethodTraitItem(ref sig, _) => {
is_static_method = sig.explicit_self.node == hir::SelfStatic;
TraitItemKind::Const(..) => (Def::AssociatedConst(item_def_id), ValueNS),
TraitItemKind::Method(ref sig, _) => {
is_static_method = sig.explicit_self.node == SelfKind::Static;
(Def::Method(item_def_id), ValueNS)
}
hir::TypeTraitItem(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS),
TraitItemKind::Type(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS),
};
self.define(module_parent, item.name, ns, (def, item.span, vis));
self.define(module_parent, item.ident.name, ns, (def, item.span, vis));
self.trait_item_map.insert((item.name, def_id), is_static_method);
self.trait_item_map.insert((item.ident.name, def_id), is_static_method);
}
}
ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
}
}
......@@ -359,16 +357,16 @@ fn build_reduced_graph_for_variant(&mut self,
item_id: DefId,
parent: Module<'b>,
vis: ty::Visibility) {
let name = variant.node.name;
let name = variant.node.name.name;
if variant.node.data.is_struct() {
// Not adding fields for variants as they are not accessed with a self receiver
let variant_def_id = self.ast_map.local_def_id(variant.node.data.id());
let variant_def_id = self.definitions.local_def_id(variant.node.data.id());
self.structs.insert(variant_def_id, Vec::new());
}
// Variants are always treated as importable to allow them to be glob used.
// All variants are defined in both type and value namespaces as future-proofing.
let def = Def::Variant(item_id, self.ast_map.local_def_id(variant.node.data.id()));
let def = Def::Variant(item_id, self.definitions.local_def_id(variant.node.data.id()));
self.define(parent, name, ValueNS, (def, variant.span, vis));
self.define(parent, name, TypeNS, (def, variant.span, vis));
}
......@@ -377,14 +375,14 @@ fn build_reduced_graph_for_variant(&mut self,
fn build_reduced_graph_for_foreign_item(&mut self,
foreign_item: &ForeignItem,
parent: Module<'b>) {
let name = foreign_item.name;
let name = foreign_item.ident.name;
let def = match foreign_item.node {
ForeignItemFn(..) => {
Def::Fn(self.ast_map.local_def_id(foreign_item.id))
ForeignItemKind::Fn(..) => {
Def::Fn(self.definitions.local_def_id(foreign_item.id))
}
ForeignItemStatic(_, m) => {
Def::Static(self.ast_map.local_def_id(foreign_item.id), m)
ForeignItemKind::Static(_, m) => {
Def::Static(self.definitions.local_def_id(foreign_item.id), m)
}
};
self.current_module = parent;
......@@ -526,20 +524,16 @@ pub fn populate_module_if_necessary(&mut self, module: Module<'b>) {
}
}
struct BuildReducedGraphVisitor<'a, 'b: 'a, 'tcx: 'b> {
resolver: &'a mut Resolver<'b, 'tcx>,
struct BuildReducedGraphVisitor<'a, 'b: 'a> {
resolver: &'a mut Resolver<'b>,
parent: Module<'b>,
}
impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
fn visit_nested_item(&mut self, item: hir::ItemId) {
self.visit_item(self.resolver.ast_map.expect_item(item.id))
}
impl<'a, 'b, 'v> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b> {
fn visit_item(&mut self, item: &Item) {
let old_parent = self.parent;
self.resolver.build_reduced_graph_for_item(item, &mut self.parent);
intravisit::walk_item(self, item);
visit::walk_item(self, item);
self.parent = old_parent;
}
......@@ -550,7 +544,7 @@ fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
fn visit_block(&mut self, block: &Block) {
let old_parent = self.parent;
self.resolver.build_reduced_graph_for_block(block, &mut self.parent);
intravisit::walk_block(self, block);
visit::walk_block(self, block);
self.parent = old_parent;
}
}
......@@ -25,33 +25,31 @@
use Namespace::{TypeNS, ValueNS};
use rustc::lint;
use syntax::ast;
use syntax::ast::{self, ViewPathGlob, ViewPathList, ViewPathSimple};
use syntax::visit::{self, Visitor};
use syntax::codemap::{Span, DUMMY_SP};
use rustc::hir;
use rustc::hir::{ViewPathGlob, ViewPathList, ViewPathSimple};
use rustc::hir::intravisit::Visitor;
struct UnusedImportCheckVisitor<'a, 'b: 'a, 'tcx: 'b> {
resolver: &'a mut Resolver<'b, 'tcx>,
struct UnusedImportCheckVisitor<'a, 'b: 'a> {
resolver: &'a mut Resolver<'b>,
}
// Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver.
impl<'a, 'b, 'tcx:'b> Deref for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
type Target = Resolver<'b, 'tcx>;
impl<'a, 'b> Deref for UnusedImportCheckVisitor<'a, 'b> {
type Target = Resolver<'b>;
fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> {
fn deref<'c>(&'c self) -> &'c Resolver<'b> {
&*self.resolver
}
}
impl<'a, 'b, 'tcx:'b> DerefMut for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> {
impl<'a, 'b> DerefMut for UnusedImportCheckVisitor<'a, 'b> {
fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> {
&mut *self.resolver
}
}
impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> {
// We have information about whether `use` (import) directives are actually
// used now. If an import is not used at all, we signal a lint error.
fn check_import(&mut self, id: ast::NodeId, span: Span) {
......@@ -73,18 +71,19 @@ fn check_import(&mut self, id: ast::NodeId, span: Span) {
}
}
impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
impl<'a, 'b, 'v> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b> {
fn visit_item(&mut self, item: &ast::Item) {
visit::walk_item(self, item);
// Ignore is_public import statements because there's no way to be sure
// whether they're used or not. Also ignore imports with a dummy span
// because this means that they were generated in some fashion by the
// compiler and we don't need to consider them.
if item.vis == hir::Public || item.span.source_equal(&DUMMY_SP) {
if item.vis == ast::Visibility::Public || item.span.source_equal(&DUMMY_SP) {
return;
}
match item.node {
hir::ItemExternCrate(_) => {
ast::ItemKind::ExternCrate(_) => {
if let Some(crate_num) = self.session.cstore.extern_mod_stmt_cnum(item.id) {
if !self.used_crates.contains(&crate_num) {
self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATES,
......@@ -94,7 +93,7 @@ fn visit_item(&mut self, item: &hir::Item) {
}
}
}
hir::ItemUse(ref p) => {
ast::ItemKind::Use(ref p) => {
match p.node {
ViewPathSimple(_, _) => {
self.check_import(item.id, p.span)
......@@ -115,7 +114,7 @@ fn visit_item(&mut self, item: &hir::Item) {
}
}
pub fn check_crate(resolver: &mut Resolver, krate: &hir::Crate) {
pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
let mut visitor = UnusedImportCheckVisitor { resolver: resolver };
krate.visit_all_items(&mut visitor);
visit::walk_crate(&mut visitor, krate);
}
此差异已折叠。
......@@ -344,11 +344,11 @@ struct ImportResolvingError<'a> {
help: String,
}
struct ImportResolver<'a, 'b: 'a, 'tcx: 'b> {
resolver: &'a mut Resolver<'b, 'tcx>,
struct ImportResolver<'a, 'b: 'a> {
resolver: &'a mut Resolver<'b>,
}
impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
impl<'a, 'b:'a> ImportResolver<'a, 'b> {
// Import resolution
//
// This is a fixed-point algorithm. We resolve imports until our efforts
......@@ -700,7 +700,7 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>, report_unresolved_impo
if reexports.len() > 0 {
if let Some(def_id) = module.def_id() {
let node_id = self.resolver.ast_map.as_local_node_id(def_id).unwrap();
let node_id = self.resolver.definitions.as_local_node_id(def_id).unwrap();
self.resolver.export_map.insert(node_id, reexports);
}
}
......
......@@ -551,6 +551,44 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
impl Pat {
pub fn walk<F>(&self, it: &mut F) -> bool
where F: FnMut(&Pat) -> bool
{
if !it(self) {
return false;
}
match self.node {
PatKind::Ident(_, _, Some(ref p)) => p.walk(it),
PatKind::Struct(_, ref fields, _) => {
fields.iter().all(|field| field.node.pat.walk(it))
}
PatKind::TupleStruct(_, Some(ref s)) | PatKind::Tup(ref s) => {
s.iter().all(|p| p.walk(it))
}
PatKind::Box(ref s) | PatKind::Ref(ref s, _) => {
s.walk(it)
}
PatKind::Vec(ref before, ref slice, ref after) => {
before.iter().all(|p| p.walk(it)) &&
slice.iter().all(|p| p.walk(it)) &&
after.iter().all(|p| p.walk(it))
}
PatKind::Wild |
PatKind::Lit(_) |
PatKind::Range(_, _) |
PatKind::Ident(_, _, _) |
PatKind::TupleStruct(..) |
PatKind::Path(..) |
PatKind::QPath(_, _) |
PatKind::Mac(_) => {
true
}
}
}
}
/// A single field in a struct pattern
///
/// Patterns like the fields of Foo `{ x, ref y, ref mut z }`
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册