Move resolution to before lowering

This commit is contained in:
Jeffrey Seyfried 2016-04-24 03:26:10 +00:00
parent 16c8f2cca8
commit 8428447253
8 changed files with 398 additions and 321 deletions

View File

@ -1438,7 +1438,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
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 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
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 = {

View File

@ -195,6 +195,10 @@ impl Definitions {
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());

View File

@ -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,

View File

@ -29,18 +29,15 @@ use rustc::ty::{self, VariantKind};
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 @@ impl<'a> ToNameBinding<'a> for (Def, Span, ty::Visibility) {
}
}
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 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
}
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 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
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 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
/// 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 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
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 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
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 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
}
};
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 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
}
}
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 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
}
}
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 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
// 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 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
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 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
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 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
}
}
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 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
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;
}
}

View File

@ -25,33 +25,31 @@ use Resolver;
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 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
}
}
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 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
}
}
}
hir::ItemUse(ref p) => {
ast::ItemKind::Use(ref p) => {
match p.node {
ViewPathSimple(_, _) => {
self.check_import(item.id, p.span)
@ -115,7 +114,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
}
}
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);
}

View File

@ -43,18 +43,18 @@ use self::AssocItemResolveResult::*;
use self::BareIdentifierPatternResolution::*;
use self::ParentLink::*;
use rustc::dep_graph::DepNode;
use rustc::hir::map as hir_map;
use rustc::hir::map::Definitions;
use rustc::hir::{PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr};
use rustc::session::Session;
use rustc::lint;
use rustc::hir::def::*;
use rustc::hir::def_id::DefId;
use rustc::hir::pat_util::pat_bindings;
use rustc::ty;
use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace};
use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet};
use syntax::ext::mtwt;
use syntax::ast::{self, FloatTy};
use syntax::ast::{CRATE_NODE_ID, Name, NodeId, CrateNum, IntTy, UintTy};
use syntax::codemap::{self, Span, Pos};
@ -62,23 +62,12 @@ use syntax::errors::DiagnosticBuilder;
use syntax::parse::token::{self, keywords};
use syntax::util::lev_distance::find_best_match_for_name;
use rustc::hir::intravisit::{self, FnKind, Visitor};
use rustc::hir;
use rustc::hir::{Arm, BindByRef, BindByValue, BindingMode, Block};
use rustc::hir::Crate;
use rustc::hir::{Expr, ExprAgain, ExprBreak, ExprField};
use rustc::hir::{ExprLoop, ExprWhile, ExprMethodCall};
use rustc::hir::{ExprPath, ExprStruct, FnDecl};
use rustc::hir::{ForeignItemFn, ForeignItemStatic, Generics};
use rustc::hir::{ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate};
use rustc::hir::{ItemFn, ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaultImpl};
use rustc::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
use rustc::hir::Local;
use rustc::hir::{Pat, PatKind, Path, PrimTy};
use rustc::hir::{PathSegment, PathParameters};
use rustc::hir::HirVec;
use rustc::hir::{TraitRef, Ty, TyBool, TyChar, TyFloat, TyInt};
use rustc::hir::{TyRptr, TyStr, TyUint, TyPath};
use syntax::visit::{self, FnKind, Visitor};
use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind};
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics};
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
use syntax::ast::{Local, Pat, PatKind, Path};
use syntax::ast::{PathSegment, PathParameters, TraitItemKind, TraitRef, Ty, TyKind};
use std::collections::{HashMap, HashSet};
use std::cell::{Cell, RefCell};
@ -197,16 +186,16 @@ enum UnresolvedNameContext<'a> {
Other,
}
fn resolve_error<'b, 'a: 'b, 'tcx: 'a, 'c>(resolver: &'b Resolver<'a, 'tcx>,
fn resolve_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
span: syntax::codemap::Span,
resolution_error: ResolutionError<'c>) {
resolve_struct_error(resolver, span, resolution_error).emit();
}
fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a, 'c>(resolver: &'b Resolver<'a, 'tcx>,
fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
span: syntax::codemap::Span,
resolution_error: ResolutionError<'b>)
-> DiagnosticBuilder<'c> {
resolution_error: ResolutionError<'c>)
-> DiagnosticBuilder<'a> {
if !resolver.emit_errors {
return resolver.session.diagnostic().struct_dummy();
}
@ -424,13 +413,13 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a, 'c>(resolver: &'b Resolver<'a, 'tc
UnresolvedNameContext::Other => { } // no help available
UnresolvedNameContext::PathIsMod(parent) => {
err.help(&match parent.map(|parent| &parent.node) {
Some(&ExprField(_, ident)) => {
Some(&ExprKind::Field(_, ident)) => {
format!("To reference an item from the `{module}` module, \
use `{module}::{ident}`",
module = path,
ident = ident.node)
}
Some(&ExprMethodCall(ident, _, _)) => {
Some(&ExprKind::MethodCall(ident, _, _)) => {
format!("To call a function from the `{module}` module, \
use `{module}::{ident}(..)`",
module = path,
@ -528,10 +517,7 @@ pub enum Namespace {
ValueNS,
}
impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
fn visit_nested_item(&mut self, item: hir::ItemId) {
self.visit_item(self.ast_map.expect_item(item.id))
}
impl<'a, 'v> Visitor<'v> for Resolver<'a> {
fn visit_item(&mut self, item: &Item) {
self.resolve_item(item);
}
@ -553,7 +539,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
fn visit_generics(&mut self, generics: &Generics) {
self.resolve_generics(generics);
}
fn visit_poly_trait_ref(&mut self, tref: &hir::PolyTraitRef, m: &hir::TraitBoundModifier) {
fn visit_poly_trait_ref(&mut self, tref: &ast::PolyTraitRef, m: &ast::TraitBoundModifier) {
match self.resolve_trait_reference(tref.trait_ref.ref_id, &tref.trait_ref.path, 0) {
Ok(def) => self.record_def(tref.trait_ref.ref_id, def),
Err(_) => {
@ -561,10 +547,10 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
self.record_def(tref.trait_ref.ref_id, err_path_resolution())
}
}
intravisit::walk_poly_trait_ref(self, tref, m);
visit::walk_poly_trait_ref(self, tref, m);
}
fn visit_variant(&mut self,
variant: &hir::Variant,
variant: &ast::Variant,
generics: &Generics,
item_id: ast::NodeId) {
if let Some(ref dis_expr) = variant.node.disr_expr {
@ -574,22 +560,22 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
});
}
// `intravisit::walk_variant` without the discriminant expression.
// `visit::walk_variant` without the discriminant expression.
self.visit_variant_data(&variant.node.data,
variant.node.name,
generics,
item_id,
variant.span);
}
fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem) {
fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
let type_parameters = match foreign_item.node {
ForeignItemFn(_, ref generics) => {
ForeignItemKind::Fn(_, ref generics) => {
HasTypeParameters(generics, FnSpace, ItemRibKind)
}
ForeignItemStatic(..) => NoTypeParameters,
ForeignItemKind::Static(..) => NoTypeParameters,
};
self.with_type_parameter_rib(type_parameters, |this| {
intravisit::walk_foreign_item(this, foreign_item);
visit::walk_foreign_item(this, foreign_item);
});
}
fn visit_fn(&mut self,
@ -599,16 +585,16 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
_: Span,
node_id: NodeId) {
let rib_kind = match function_kind {
FnKind::ItemFn(_, generics, _, _, _, _, _) => {
FnKind::ItemFn(_, generics, _, _, _, _) => {
self.visit_generics(generics);
ItemRibKind
}
FnKind::Method(_, sig, _, _) => {
FnKind::Method(_, sig, _) => {
self.visit_generics(&sig.generics);
self.visit_explicit_self(&sig.explicit_self);
MethodRibKind
}
FnKind::Closure(_) => ClosureRibKind(node_id),
FnKind::Closure => ClosureRibKind(node_id),
};
self.resolve_function(rib_kind, declaration, block);
}
@ -648,17 +634,17 @@ enum FallbackSuggestion {
}
#[derive(Copy, Clone)]
enum TypeParameters<'tcx, 'a> {
enum TypeParameters<'a, 'b> {
NoTypeParameters,
HasTypeParameters(// Type parameters.
&'a Generics,
&'b Generics,
// Identifies the things that these parameters
// were declared on (type, fn, etc)
ParamSpace,
// The kind of the rib used for type parameters.
RibKind<'tcx>),
RibKind<'a>),
}
// The rib kind controls the translation of local
@ -973,10 +959,10 @@ impl PrimitiveTypeTable {
}
/// The main resolver class.
pub struct Resolver<'a, 'tcx: 'a> {
pub struct Resolver<'a> {
session: &'a Session,
ast_map: &'a hir_map::Map<'tcx>,
definitions: &'a Definitions,
graph_root: Module<'a>,
@ -1081,9 +1067,9 @@ impl<'a> ResolverArenas<'a> {
}
}
impl<'a, 'tcx> ty::NodeIdTree for Resolver<'a, 'tcx> {
impl<'a> ty::NodeIdTree for Resolver<'a> {
fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool {
let ancestor = self.ast_map.local_def_id(ancestor);
let ancestor = self.definitions.local_def_id(ancestor);
let mut module = *self.module_map.get(&node).unwrap();
while module.def_id() != Some(ancestor) {
let module_parent = match self.get_nearest_normal_module_parent(module) {
@ -1096,13 +1082,13 @@ impl<'a, 'tcx> ty::NodeIdTree for Resolver<'a, 'tcx> {
}
}
impl<'a, 'tcx> Resolver<'a, 'tcx> {
impl<'a> Resolver<'a> {
fn new(session: &'a Session,
ast_map: &'a hir_map::Map<'tcx>,
definitions: &'a Definitions,
make_glob_map: MakeGlobMap,
arenas: &'a ResolverArenas<'a>)
-> Resolver<'a, 'tcx> {
let root_def_id = ast_map.local_def_id(CRATE_NODE_ID);
-> Resolver<'a> {
let root_def_id = definitions.local_def_id(CRATE_NODE_ID);
let graph_root =
ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, arenas);
let graph_root = arenas.alloc_module(graph_root);
@ -1112,7 +1098,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
Resolver {
session: session,
ast_map: ast_map,
definitions: definitions,
// The outermost module has def ID 0; this is not reflected in the
// AST.
@ -1335,7 +1321,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// This is not a crate-relative path. We resolve the
// first component of the path in the current lexical
// scope and then proceed to resolve below that.
let ident = hir::Ident::from_name(module_path[0]);
let ident = ast::Ident::with_empty_ctxt(module_path[0]);
match self.resolve_ident_in_lexical_scope(ident, TypeNS, true)
.and_then(LexicalScopeBinding::module) {
None => return Failed(None),
@ -1377,11 +1363,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// Invariant: This must only be called during main resolution, not during
/// import resolution.
fn resolve_ident_in_lexical_scope(&mut self,
ident: hir::Ident,
ident: ast::Ident,
ns: Namespace,
record_used: bool)
-> Option<LexicalScopeBinding<'a>> {
let name = match ns { ValueNS => ident.name, TypeNS => ident.unhygienic_name };
let name = match ns { ValueNS => mtwt::resolve(ident), TypeNS => ident.name };
// Walk backwards up the ribs in scope.
for i in (0 .. self.get_ribs(ns).len()).rev() {
@ -1394,7 +1380,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
if let ModuleRibKind(module) = self.get_ribs(ns)[i].kind {
let name = ident.unhygienic_name;
let name = ident.name;
let item = self.resolve_name_in_module(module, name, ns, true, record_used);
if let Success(binding) = item {
// The ident resolves to an item.
@ -1563,77 +1549,76 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
None
}
fn resolve_crate(&mut self, krate: &hir::Crate) {
fn resolve_crate(&mut self, krate: &Crate) {
debug!("(resolving crate) starting");
self.current_module = self.graph_root;
intravisit::walk_crate(self, krate);
visit::walk_crate(self, krate);
}
fn resolve_item(&mut self, item: &Item) {
let name = item.name;
let name = item.ident.name;
debug!("(resolving item) resolving {}", name);
match item.node {
ItemEnum(_, ref generics) |
ItemTy(_, ref generics) |
ItemStruct(_, ref generics) => {
ItemKind::Enum(_, ref generics) |
ItemKind::Ty(_, ref generics) |
ItemKind::Struct(_, ref generics) => {
self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, ItemRibKind),
|this| intravisit::walk_item(this, item));
|this| visit::walk_item(this, item));
}
ItemFn(_, _, _, _, ref generics, _) => {
ItemKind::Fn(_, _, _, _, ref generics, _) => {
self.with_type_parameter_rib(HasTypeParameters(generics, FnSpace, ItemRibKind),
|this| intravisit::walk_item(this, item));
|this| visit::walk_item(this, item));
}
ItemDefaultImpl(_, ref trait_ref) => {
ItemKind::DefaultImpl(_, ref trait_ref) => {
self.with_optional_trait_ref(Some(trait_ref), |_, _| {});
}
ItemImpl(_, _, ref generics, ref opt_trait_ref, ref self_type, ref impl_items) => {
ItemKind::Impl(_, _, ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
self.resolve_implementation(generics,
opt_trait_ref,
&self_type,
item.id,
impl_items);
}
impl_items),
ItemTrait(_, ref generics, ref bounds, ref trait_items) => {
ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => {
// Create a new rib for the trait-wide type parameters.
self.with_type_parameter_rib(HasTypeParameters(generics,
TypeSpace,
ItemRibKind),
|this| {
let local_def_id = this.ast_map.local_def_id(item.id);
let local_def_id = this.definitions.local_def_id(item.id);
this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
this.visit_generics(generics);
walk_list!(this, visit_ty_param_bound, bounds);
for trait_item in trait_items {
match trait_item.node {
hir::ConstTraitItem(_, ref default) => {
TraitItemKind::Const(_, ref default) => {
// Only impose the restrictions of
// ConstRibKind if there's an actual constant
// expression in a provided default.
if default.is_some() {
this.with_constant_rib(|this| {
intravisit::walk_trait_item(this, trait_item)
visit::walk_trait_item(this, trait_item)
});
} else {
intravisit::walk_trait_item(this, trait_item)
visit::walk_trait_item(this, trait_item)
}
}
hir::MethodTraitItem(ref sig, _) => {
TraitItemKind::Method(ref sig, _) => {
let type_parameters =
HasTypeParameters(&sig.generics,
FnSpace,
MethodRibKind);
this.with_type_parameter_rib(type_parameters, |this| {
intravisit::walk_trait_item(this, trait_item)
visit::walk_trait_item(this, trait_item)
});
}
hir::TypeTraitItem(..) => {
TraitItemKind::Type(..) => {
this.with_type_parameter_rib(NoTypeParameters, |this| {
intravisit::walk_trait_item(this, trait_item)
visit::walk_trait_item(this, trait_item)
});
}
};
@ -1642,21 +1627,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
});
}
ItemMod(_) | ItemForeignMod(_) => {
ItemKind::Mod(_) | ItemKind::ForeignMod(_) => {
self.with_scope(item.id, |this| {
intravisit::walk_item(this, item);
visit::walk_item(this, item);
});
}
ItemConst(..) | ItemStatic(..) => {
ItemKind::Const(..) | ItemKind::Static(..) => {
self.with_constant_rib(|this| {
intravisit::walk_item(this, item);
visit::walk_item(this, item);
});
}
ItemUse(ref view_path) => {
ItemKind::Use(ref view_path) => {
match view_path.node {
hir::ViewPathList(ref prefix, ref items) => {
ast::ViewPathList(ref prefix, ref items) => {
// Resolve prefix of an import with empty braces (issue #28388)
if items.is_empty() && !prefix.segments.is_empty() {
match self.resolve_crate_relative_path(prefix.span,
@ -1681,9 +1666,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
ItemExternCrate(_) => {
ItemKind::ExternCrate(_) => {
// do nothing, these are just around to be encoded
}
ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
}
}
@ -1695,7 +1682,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let mut function_type_rib = Rib::new(rib_kind);
let mut seen_bindings = HashSet::new();
for (index, type_parameter) in generics.ty_params.iter().enumerate() {
let name = type_parameter.name;
let name = type_parameter.ident.name;
debug!("with_type_parameter_rib: {}", type_parameter.id);
if seen_bindings.contains(&name) {
@ -1706,7 +1693,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
seen_bindings.insert(name);
// plain insert (no renaming)
let def_id = self.ast_map.local_def_id(type_parameter.id);
let def_id = self.definitions.local_def_id(type_parameter.id);
let def = Def::TyParam(space, index as u32, def_id, name);
function_type_rib.bindings.insert(name, def);
}
@ -1759,7 +1746,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
debug!("(resolving function) recorded argument");
}
intravisit::walk_fn_ret_ty(self, &declaration.output);
visit::walk_fn_ret_ty(self, &declaration.output);
// Resolve the function body.
self.visit_block(block);
@ -1836,9 +1823,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
fn resolve_generics(&mut self, generics: &Generics) {
for predicate in &generics.where_clause.predicates {
match predicate {
&hir::WherePredicate::BoundPredicate(_) |
&hir::WherePredicate::RegionPredicate(_) => {}
&hir::WherePredicate::EqPredicate(ref eq_pred) => {
&ast::WherePredicate::BoundPredicate(_) |
&ast::WherePredicate::RegionPredicate(_) => {}
&ast::WherePredicate::EqPredicate(ref eq_pred) => {
self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS).and_then(|path_res| {
if let PathResolution { base_def: Def::TyParam(..), .. } = path_res {
Ok(self.record_def(eq_pred.id, path_res))
@ -1854,7 +1841,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
}
intravisit::walk_generics(self, generics);
visit::walk_generics(self, generics);
}
fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T
@ -1883,7 +1870,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} else {
self.record_def(trait_ref.ref_id, err_path_resolution());
}
intravisit::walk_trait_ref(self, trait_ref);
visit::walk_trait_ref(self, trait_ref);
}
let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
let result = f(self, new_id);
@ -1927,20 +1914,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
for impl_item in impl_items {
this.resolve_visibility(&impl_item.vis);
match impl_item.node {
hir::ImplItemKind::Const(..) => {
ImplItemKind::Const(..) => {
// If this is a trait impl, ensure the const
// exists in trait
this.check_trait_item(impl_item.name,
this.check_trait_item(impl_item.ident.name,
impl_item.span,
|n, s| ResolutionError::ConstNotMemberOfTrait(n, s));
this.with_constant_rib(|this| {
intravisit::walk_impl_item(this, impl_item);
visit::walk_impl_item(this, impl_item);
});
}
hir::ImplItemKind::Method(ref sig, _) => {
ImplItemKind::Method(ref sig, _) => {
// If this is a trait impl, ensure the method
// exists in trait
this.check_trait_item(impl_item.name,
this.check_trait_item(impl_item.ident.name,
impl_item.span,
|n, s| ResolutionError::MethodNotMemberOfTrait(n, s));
@ -1951,18 +1938,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
FnSpace,
MethodRibKind);
this.with_type_parameter_rib(type_parameters, |this| {
intravisit::walk_impl_item(this, impl_item);
visit::walk_impl_item(this, impl_item);
});
}
hir::ImplItemKind::Type(ref ty) => {
ImplItemKind::Type(ref ty) => {
// If this is a trait impl, ensure the type
// exists in trait
this.check_trait_item(impl_item.name,
this.check_trait_item(impl_item.ident.name,
impl_item.span,
|n, s| ResolutionError::TypeNotMemberOfTrait(n, s));
this.visit_ty(ty);
}
ImplItemKind::Macro(_) => panic!("unexpanded macro in resolve!"),
}
}
});
@ -2000,18 +1988,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// that expands into an or-pattern where one 'x' was from the
// user and one 'x' came from the macro.
fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
let mut result = HashMap::new();
let def_map = RefCell::new(::std::mem::replace(&mut self.def_map, NodeMap()));
pat_bindings(&def_map, pat, |binding_mode, _id, sp, path1| {
let name = path1.node;
result.insert(name,
BindingInfo {
span: sp,
binding_mode: binding_mode,
let mut binding_map = HashMap::new();
pat.walk(&mut |pat| {
if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node {
if sub_pat.is_some() || match self.def_map.get(&pat.id) {
Some(&PathResolution { base_def: Def::Local(..), .. }) => true,
_ => false,
} {
let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode };
binding_map.insert(mtwt::resolve(ident.node), binding_info);
}
}
true
});
});
self.def_map = def_map.into_inner();
return result;
binding_map
}
// check that all of the arms in an or-pattern have exactly the
@ -2086,7 +2078,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
// Descend into the block.
intravisit::walk_block(self, block);
visit::walk_block(self, block);
// Move back up.
self.current_module = orig_module;
@ -2099,7 +2091,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
fn resolve_type(&mut self, ty: &Ty) {
match ty.node {
TyPath(ref maybe_qself, ref path) => {
TyKind::Path(ref maybe_qself, ref path) => {
let resolution = match self.resolve_possibly_assoc_item(ty.id,
maybe_qself.as_ref(),
path,
@ -2107,7 +2099,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// `<T>::a::b::c` is resolved by typeck alone.
TypecheckRequired => {
// Resolve embedded types.
intravisit::walk_ty(self, ty);
visit::walk_ty(self, ty);
return;
}
ResolveAttempt(resolution) => resolution,
@ -2176,7 +2168,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
_ => {}
}
// Resolve embedded types.
intravisit::walk_ty(self, ty);
visit::walk_ty(self, ty);
}
fn resolve_pattern(&mut self,
@ -2186,7 +2178,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// pattern that binds them
bindings_list: &mut HashMap<Name, NodeId>) {
let pat_id = pattern.id;
pattern.walk(|pattern| {
pattern.walk(&mut |pattern| {
match pattern.node {
PatKind::Ident(binding_mode, ref path1, ref at_rhs) => {
// The meaning of PatKind::Ident with no type parameters
@ -2200,7 +2192,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let const_ok = mode == RefutableMode && at_rhs.is_none();
let ident = path1.node;
let renamed = ident.name;
let renamed = mtwt::resolve(ident);
match self.resolve_bare_identifier_pattern(ident, pattern.span) {
FoundStructOrEnumVariant(def) if const_ok => {
@ -2246,7 +2238,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
BareIdentifierPatternUnresolved => {
debug!("(resolving pattern) binding `{}`", renamed);
let def_id = self.ast_map.local_def_id(pattern.id);
let def_id = self.definitions.local_def_id(pattern.id);
let def = Def::Local(def_id, pattern.id);
// Record the definition so that later passes
@ -2370,7 +2362,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
);
self.record_def(pattern.id, err_path_resolution());
}
intravisit::walk_path(self, path);
visit::walk_path(self, path);
}
PatKind::QPath(ref qself, ref path) => {
@ -2390,7 +2382,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
.name;
let traits = self.get_traits_containing_item(const_name);
self.trait_map.insert(pattern.id, traits);
intravisit::walk_pat(self, pattern);
visit::walk_pat(self, pattern);
return true;
}
ResolveAttempt(resolution) => resolution,
@ -2424,7 +2416,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
.as_str()));
self.record_def(pattern.id, err_path_resolution());
}
intravisit::walk_pat(self, pattern);
visit::walk_pat(self, pattern);
}
PatKind::Struct(ref path, _, _) => {
@ -2443,11 +2435,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
self.record_def(pattern.id, err_path_resolution());
}
}
intravisit::walk_path(self, path);
visit::walk_path(self, path);
}
PatKind::Lit(_) | PatKind::Range(..) => {
intravisit::walk_pat(self, pattern);
visit::walk_pat(self, pattern);
}
_ => {
@ -2458,7 +2450,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
});
}
fn resolve_bare_identifier_pattern(&mut self, ident: hir::Ident, span: Span)
fn resolve_bare_identifier_pattern(&mut self, ident: ast::Ident, span: Span)
-> BareIdentifierPatternResolution {
let binding = match self.resolve_ident_in_lexical_scope(ident, ValueNS, true) {
Some(LexicalScopeBinding::Item(binding)) => binding,
@ -2468,7 +2460,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
match def {
Def::Variant(..) | Def::Struct(..) => FoundStructOrEnumVariant(def),
Def::Const(..) | Def::AssociatedConst(..) => FoundConst(def, ident.unhygienic_name),
Def::Const(..) | Def::AssociatedConst(..) => FoundConst(def, ident.name),
Def::Static(..) => {
let error = ResolutionError::StaticVariableReference(binding);
resolve_error(self, span, error);
@ -2481,7 +2473,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// Handles paths that may refer to associated items
fn resolve_possibly_assoc_item(&mut self,
id: NodeId,
maybe_qself: Option<&hir::QSelf>,
maybe_qself: Option<&ast::QSelf>,
path: &Path,
namespace: Namespace)
-> AssocItemResolveResult {
@ -2542,7 +2534,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
None | Some(LocalDef{def: Def::Mod(..), ..}) if namespace == TypeNS =>
this.primitive_type_table
.primitive_types
.get(&last_ident.unhygienic_name)
.get(&last_ident.name)
.map_or(def, |prim_ty| Some(LocalDef::from_def(Def::PrimTy(*prim_ty)))),
_ => def
}
@ -2583,11 +2575,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// Resolve a single identifier
fn resolve_identifier(&mut self,
identifier: hir::Ident,
identifier: ast::Ident,
namespace: Namespace,
record_used: bool)
-> Option<LocalDef> {
if identifier.unhygienic_name == keywords::Invalid.name() {
if identifier.name == keywords::Invalid.name() {
return Some(LocalDef::from_def(Def::Err));
}
@ -2615,7 +2607,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
ClosureRibKind(function_id) => {
let prev_def = def;
let node_def_id = self.ast_map.local_def_id(node_id);
let node_def_id = self.definitions.local_def_id(node_id);
let seen = self.freevars_seen
.entry(function_id)
@ -2687,7 +2679,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// resolve a "module-relative" path, e.g. a::b::c
fn resolve_module_relative_path(&mut self,
span: Span,
segments: &[hir::PathSegment],
segments: &[ast::PathSegment],
namespace: Namespace)
-> Result<&'a NameBinding<'a>,
bool /* true if an error was reported */> {
@ -2731,7 +2723,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// import resolution.
fn resolve_crate_relative_path(&mut self,
span: Span,
segments: &[hir::PathSegment],
segments: &[ast::PathSegment],
namespace: Namespace)
-> Result<&'a NameBinding<'a>,
bool /* true if an error was reported */> {
@ -2790,8 +2782,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion {
fn extract_node_id(t: &Ty) -> Option<NodeId> {
match t.node {
TyPath(None, _) => Some(t.id),
TyRptr(_, ref mut_ty) => extract_node_id(&mut_ty.ty),
TyKind::Path(None, _) => Some(t.id),
TyKind::Rptr(_, ref mut_ty) => extract_node_id(&mut_ty.ty),
// This doesn't handle the remaining `Ty` variants as they are not
// that commonly the self_type, it might be interesting to provide
// support for those in future.
@ -2849,6 +2841,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} SuggestionType::NotFound
}
fn resolve_labeled_block(&mut self, label: Option<ast::Ident>, id: NodeId, block: &Block) {
if let Some(label) = label {
let (label, def) = (mtwt::resolve(label), Def::Label(id));
self.with_label_rib(|this| {
this.label_ribs.last_mut().unwrap().bindings.insert(label, def);
this.visit_block(block);
});
} else {
self.visit_block(block);
}
}
fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
// First, record candidate traits for this expression if it could
// result in the invocation of a method call.
@ -2857,7 +2861,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// Next, resolve the node.
match expr.node {
ExprPath(ref maybe_qself, ref path) => {
ExprKind::Path(ref maybe_qself, ref path) => {
let resolution = match self.resolve_possibly_assoc_item(expr.id,
maybe_qself.as_ref(),
path,
@ -2867,7 +2871,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let method_name = path.segments.last().unwrap().identifier.name;
let traits = self.get_traits_containing_item(method_name);
self.trait_map.insert(expr.id, traits);
intravisit::walk_expr(self, expr);
visit::walk_expr(self, expr);
return;
}
ResolveAttempt(resolution) => resolution,
@ -3009,10 +3013,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
intravisit::walk_expr(self, expr);
visit::walk_expr(self, expr);
}
ExprStruct(ref path, _, _) => {
ExprKind::Struct(ref path, _, _) => {
// Resolve the path to the structure it goes to. We don't
// check to ensure that the path is actually a structure; that
// is checked later during typeck.
@ -3031,24 +3035,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
intravisit::walk_expr(self, expr);
visit::walk_expr(self, expr);
}
ExprLoop(_, Some(label)) | ExprWhile(_, _, Some(label)) => {
ExprKind::Loop(_, Some(label)) | ExprKind::While(_, _, Some(label)) => {
self.with_label_rib(|this| {
let def = Def::Label(expr.id);
{
let rib = this.label_ribs.last_mut().unwrap();
rib.bindings.insert(label.name, def);
rib.bindings.insert(mtwt::resolve(label), def);
}
intravisit::walk_expr(this, expr);
visit::walk_expr(this, expr);
})
}
ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
match self.search_label(label.node.name) {
ExprKind::Break(Some(label)) | ExprKind::Again(Some(label)) => {
match self.search_label(mtwt::resolve(label.node)) {
None => {
self.record_def(expr.id, err_path_resolution());
resolve_error(self,
@ -3068,10 +3072,42 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
}
ExprField(ref subexpression, _) => {
ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => {
self.visit_expr(subexpression);
self.value_ribs.push(Rib::new(NormalRibKind));
self.resolve_pattern(pattern, RefutableMode, &mut HashMap::new());
self.visit_block(if_block);
self.value_ribs.pop();
optional_else.as_ref().map(|expr| self.visit_expr(expr));
}
ExprKind::WhileLet(ref pattern, ref subexpression, ref block, label) => {
self.visit_expr(subexpression);
self.value_ribs.push(Rib::new(NormalRibKind));
self.resolve_pattern(pattern, RefutableMode, &mut HashMap::new());
self.resolve_labeled_block(label, expr.id, block);
self.value_ribs.pop();
}
ExprKind::ForLoop(ref pattern, ref subexpression, ref block, label) => {
self.visit_expr(subexpression);
self.value_ribs.push(Rib::new(NormalRibKind));
self.resolve_pattern(pattern, LocalIrrefutableMode, &mut HashMap::new());
self.resolve_labeled_block(label, expr.id, block);
self.value_ribs.pop();
}
ExprKind::Field(ref subexpression, _) => {
self.resolve_expr(subexpression, Some(expr));
}
ExprMethodCall(_, ref types, ref arguments) => {
ExprKind::MethodCall(_, ref types, ref arguments) => {
let mut arguments = arguments.iter();
self.resolve_expr(arguments.next().unwrap(), Some(expr));
for argument in arguments {
@ -3083,25 +3119,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
_ => {
intravisit::walk_expr(self, expr);
visit::walk_expr(self, expr);
}
}
}
fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) {
match expr.node {
ExprField(_, name) => {
ExprKind::Field(_, name) => {
// FIXME(#6890): Even though you can't treat a method like a
// field, we need to add any trait methods we find that match
// the field name so that we can do some nice error reporting
// later on in typeck.
let traits = self.get_traits_containing_item(name.node);
let traits = self.get_traits_containing_item(name.node.name);
self.trait_map.insert(expr.id, traits);
}
ExprMethodCall(name, _, _) => {
ExprKind::MethodCall(name, _, _) => {
debug!("(recording candidate traits for expr) recording traits for {}",
expr.id);
let traits = self.get_traits_containing_item(name.node);
let traits = self.get_traits_containing_item(name.node.name);
self.trait_map.insert(expr.id, traits);
}
_ => {
@ -3211,7 +3247,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if let Some(def) = name_binding.def() {
if name == lookup_name && ns == namespace && filter_fn(def) {
// create the path
let ident = hir::Ident::from_name(name);
let ident = ast::Ident::with_empty_ctxt(name);
let params = PathParameters::none();
let segment = PathSegment {
identifier: ident,
@ -3220,7 +3256,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let span = name_binding.span;
let mut segms = path_segments.clone();
segms.push(segment);
let segms = HirVec::from_vec(segms);
let path = Path {
span: span,
global: true,
@ -3246,7 +3281,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
NoParentLink => path_segments.clone(),
ModuleParentLink(_, name) => {
let mut paths = path_segments.clone();
let ident = hir::Ident::from_name(name);
let ident = ast::Ident::with_empty_ctxt(name);
let params = PathParameters::none();
let segm = PathSegment {
identifier: ident,
@ -3276,11 +3311,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
debug!("(recording def) recording {:?} for {}", resolution, node_id);
if let Some(prev_res) = self.def_map.insert(node_id, resolution) {
let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP);
span_bug!(span,
"path resolved multiple times ({:?} before, {:?} now)",
prev_res,
resolution);
panic!("path resolved multiple times ({:?} before, {:?} now)", prev_res, resolution);
}
}
@ -3289,8 +3320,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
pat_binding_mode: BindingMode,
descr: &str) {
match pat_binding_mode {
BindByValue(_) => {}
BindByRef(..) => {
BindingMode::ByValue(_) => {}
BindingMode::ByRef(..) => {
resolve_error(self,
pat.span,
ResolutionError::CannotUseRefBindingModeWith(descr));
@ -3298,15 +3329,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
fn resolve_visibility(&mut self, vis: &hir::Visibility) -> ty::Visibility {
fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
let (path, id) = match *vis {
hir::Public => return ty::Visibility::Public,
hir::Visibility::Crate => return ty::Visibility::Restricted(ast::CRATE_NODE_ID),
hir::Visibility::Restricted { ref path, id } => (path, id),
hir::Inherited => {
ast::Visibility::Public => return ty::Visibility::Public,
ast::Visibility::Crate(_) => return ty::Visibility::Restricted(ast::CRATE_NODE_ID),
ast::Visibility::Restricted { ref path, id } => (path, id),
ast::Visibility::Inherited => {
let current_module =
self.get_nearest_normal_module_parent_or_self(self.current_module);
let id = self.ast_map.as_local_node_id(current_module.def_id().unwrap()).unwrap();
let id =
self.definitions.as_local_node_id(current_module.def_id().unwrap()).unwrap();
return ty::Visibility::Restricted(id);
}
};
@ -3317,7 +3349,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let def = module.def.unwrap();
let path_resolution = PathResolution { base_def: def, depth: 0 };
self.def_map.insert(id, path_resolution);
ty::Visibility::Restricted(self.ast_map.as_local_node_id(def.def_id()).unwrap())
ty::Visibility::Restricted(self.definitions.as_local_node_id(def.def_id()).unwrap())
}
Failed(Some((span, msg))) => {
self.session.span_err(span, &format!("failed to resolve module path. {}", msg));
@ -3337,7 +3369,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
fn is_accessible(&self, vis: ty::Visibility) -> bool {
let current_module = self.get_nearest_normal_module_parent_or_self(self.current_module);
let node_id = self.ast_map.as_local_node_id(current_module.def_id().unwrap()).unwrap();
let node_id = self.definitions.as_local_node_id(current_module.def_id().unwrap()).unwrap();
vis.is_accessible_from(node_id, self)
}
@ -3547,8 +3579,9 @@ pub enum MakeGlobMap {
}
/// Entry point to crate resolution.
pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
ast_map: &'a hir_map::Map<'tcx>,
pub fn resolve_crate<'a>(session: &'a Session,
krate: &'a Crate,
definitions: &'a Definitions,
make_glob_map: MakeGlobMap)
-> CrateMap {
// Currently, we ignore the name resolution data structures for
@ -3558,11 +3591,9 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
// reflects not just its contents but the results of name
// resolution on those contents. Hopefully we'll push this back at
// some point.
let _task = ast_map.dep_graph.in_task(DepNode::Resolve);
let krate = ast_map.krate();
let arenas = Resolver::arenas();
let mut resolver = create_resolver(session, ast_map, krate, make_glob_map, &arenas);
let mut resolver = create_resolver(session, definitions, krate, make_glob_map, &arenas);
resolver.resolve_crate(krate);
@ -3584,13 +3615,13 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
}
/// Builds a name resolution walker.
fn create_resolver<'a, 'tcx>(session: &'a Session,
ast_map: &'a hir_map::Map<'tcx>,
fn create_resolver<'a>(session: &'a Session,
definitions: &'a Definitions,
krate: &'a Crate,
make_glob_map: MakeGlobMap,
arenas: &'a ResolverArenas<'a>)
-> Resolver<'a, 'tcx> {
let mut resolver = Resolver::new(session, ast_map, make_glob_map, arenas);
-> Resolver<'a> {
let mut resolver = Resolver::new(session, definitions, make_glob_map, arenas);
resolver.build_reduced_graph(krate);

View File

@ -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 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
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);
}
}

View File

@ -551,6 +551,44 @@ impl fmt::Debug for Pat {
}
}
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 }`