Auto merge of #33232 - jseyfried:resolve_ast_groundwork, r=nrc

resolve: cleanup and groundwork for resolving the AST

Cleanup `resolve` and refactor away uses of the hir map (incorrectly named `ast_map`).
r? @nrc
This commit is contained in:
bors 2016-04-29 09:02:36 -07:00
commit 8b1dcf40f2
4 changed files with 132 additions and 188 deletions

View File

@ -283,6 +283,24 @@ pub enum Visibility {
PrivateExternal,
}
pub trait NodeIdTree {
fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool;
}
impl<'a> NodeIdTree for ast_map::Map<'a> {
fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool {
let mut node_ancestor = node;
while node_ancestor != ancestor {
let node_ancestor_parent = self.get_module_parent(node_ancestor);
if node_ancestor_parent == node_ancestor {
return false;
}
node_ancestor = node_ancestor_parent;
}
true
}
}
impl Visibility {
pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: &TyCtxt) -> Self {
match *visibility {
@ -301,7 +319,7 @@ impl Visibility {
}
/// Returns true if an item with this visibility is accessible from the given block.
pub fn is_accessible_from(self, block: NodeId, map: &ast_map::Map) -> bool {
pub fn is_accessible_from<T: NodeIdTree>(self, block: NodeId, tree: &T) -> bool {
let restriction = match self {
// Public items are visible everywhere.
Visibility::Public => return true,
@ -311,24 +329,18 @@ impl Visibility {
Visibility::Restricted(module) => module,
};
let mut block_ancestor = block;
loop {
if block_ancestor == restriction { return true }
let block_ancestor_parent = map.get_module_parent(block_ancestor);
if block_ancestor_parent == block_ancestor { return false }
block_ancestor = block_ancestor_parent;
}
tree.is_descendant_of(block, restriction)
}
/// Returns true if this visibility is at least as accessible as the given visibility
pub fn is_at_least(self, vis: Visibility, map: &ast_map::Map) -> bool {
pub fn is_at_least<T: NodeIdTree>(self, vis: Visibility, tree: &T) -> bool {
let vis_restriction = match vis {
Visibility::Public => return self == Visibility::Public,
Visibility::PrivateExternal => return true,
Visibility::Restricted(module) => module,
};
self.is_accessible_from(vis_restriction, map)
self.is_accessible_from(vis_restriction, tree)
}
}

View File

@ -46,15 +46,15 @@ trait ToNameBinding<'a> {
fn to_name_binding(self) -> NameBinding<'a>;
}
impl<'a> ToNameBinding<'a> for (Module<'a>, Span) {
impl<'a> ToNameBinding<'a> for (Module<'a>, Span, ty::Visibility) {
fn to_name_binding(self) -> NameBinding<'a> {
NameBinding::create_from_module(self.0, Some(self.1))
NameBinding { kind: NameBindingKind::Module(self.0), span: self.1, vis: self.2 }
}
}
impl<'a> ToNameBinding<'a> for (Def, Span, ty::Visibility) {
fn to_name_binding(self) -> NameBinding<'a> {
NameBinding { kind: NameBindingKind::Def(self.0), span: Some(self.1), vis: self.2 }
NameBinding { kind: NameBindingKind::Def(self.0), span: self.1, vis: self.2 }
}
}
@ -247,8 +247,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
};
let parent_link = ModuleParentLink(parent, name);
let def = Def::Mod(def_id);
let module = self.new_extern_crate_module(parent_link, def, vis, item.id);
self.define(parent, name, TypeNS, (module, sp));
let module = self.new_extern_crate_module(parent_link, def, item.id);
self.define(parent, name, TypeNS, (module, sp, vis));
self.build_reduced_graph_for_external_crate(module);
}
@ -257,8 +257,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
ItemMod(..) => {
let parent_link = ModuleParentLink(parent, name);
let def = Def::Mod(self.ast_map.local_def_id(item.id));
let module = self.new_module(parent_link, Some(def), false, vis);
self.define(parent, name, TypeNS, (module, sp));
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;
}
@ -289,12 +289,12 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
ItemEnum(ref enum_definition, _) => {
let parent_link = ModuleParentLink(parent, name);
let def = Def::Enum(self.ast_map.local_def_id(item.id));
let module = self.new_module(parent_link, Some(def), false, vis);
self.define(parent, name, TypeNS, (module, sp));
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);
self.build_reduced_graph_for_variant(variant, item_def_id, module);
self.build_reduced_graph_for_variant(variant, item_def_id, module, vis);
}
}
@ -328,21 +328,25 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
// Add all the items within to a new module.
let parent_link = ModuleParentLink(parent, name);
let def = Def::Trait(def_id);
let module_parent = self.new_module(parent_link, Some(def), false, vis);
self.define(parent, name, TypeNS, (module_parent, sp));
let module_parent = self.new_module(parent_link, Some(def), false);
self.define(parent, name, TypeNS, (module_parent, sp, vis));
// 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 mut is_static_method = false;
let (def, ns) = match item.node {
hir::ConstTraitItem(..) => (Def::AssociatedConst(item_def_id), ValueNS),
hir::MethodTraitItem(..) => (Def::Method(item_def_id), ValueNS),
hir::MethodTraitItem(ref sig, _) => {
is_static_method = sig.explicit_self.node == hir::SelfStatic;
(Def::Method(item_def_id), ValueNS)
}
hir::TypeTraitItem(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS),
};
self.define(module_parent, item.name, ns, (def, item.span, vis));
self.trait_item_map.insert((item.name, def_id), item_def_id);
self.trait_item_map.insert((item.name, def_id), is_static_method);
}
}
}
@ -353,7 +357,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
fn build_reduced_graph_for_variant(&mut self,
variant: &Variant,
item_id: DefId,
parent: Module<'b>) {
parent: Module<'b>,
vis: ty::Visibility) {
let name = variant.node.name;
if variant.node.data.is_struct() {
// Not adding fields for variants as they are not accessed with a self receiver
@ -364,8 +369,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
// 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()));
self.define(parent, name, ValueNS, (def, variant.span, parent.vis));
self.define(parent, name, TypeNS, (def, variant.span, parent.vis));
self.define(parent, name, ValueNS, (def, variant.span, vis));
self.define(parent, name, TypeNS, (def, variant.span, vis));
}
/// Constructs the reduced graph for one foreign item.
@ -396,7 +401,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
block_id);
let parent_link = BlockParentLink(parent, block_id);
let new_module = self.new_module(parent_link, None, false, parent.vis);
let new_module = self.new_module(parent_link, None, false);
self.module_map.insert(block_id, new_module);
*parent = new_module;
}
@ -425,8 +430,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
debug!("(building reduced graph for external crate) building module {} {:?}",
name, vis);
let parent_link = ModuleParentLink(parent, name);
let module = self.new_module(parent_link, Some(def), true, vis);
self.try_define(parent, name, TypeNS, (module, DUMMY_SP));
let module = self.new_module(parent_link, Some(def), true);
self.try_define(parent, name, TypeNS, (module, DUMMY_SP, vis));
}
Def::Variant(_, variant_id) => {
debug!("(building reduced graph for external crate) building variant {}", name);
@ -463,12 +468,12 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
'{}'",
trait_item_name);
self.trait_item_map.insert((trait_item_name, def_id), trait_item_def.def_id());
self.trait_item_map.insert((trait_item_name, def_id), false);
}
let parent_link = ModuleParentLink(parent, name);
let module = self.new_module(parent_link, Some(def), true, vis);
self.try_define(parent, name, TypeNS, (module, DUMMY_SP));
let module = self.new_module(parent_link, Some(def), true);
self.try_define(parent, name, TypeNS, (module, DUMMY_SP, vis));
}
Def::TyAlias(..) | Def::AssociatedTy(..) => {
debug!("(building reduced graph for external crate) building type {}", name);

View File

@ -42,7 +42,6 @@ use self::ModulePrefixResult::*;
use self::AssocItemResolveResult::*;
use self::BareIdentifierPatternResolution::*;
use self::ParentLink::*;
use self::FallbackChecks::*;
use rustc::dep_graph::DepNode;
use rustc::hir::map as hir_map;
@ -81,7 +80,7 @@ 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, TyPtr};
use rustc::hir::{TyRptr, TyStr, TyUint, TyPath};
use std::collections::{HashMap, HashSet};
use std::cell::{Cell, RefCell};
@ -349,7 +348,7 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
if let Some(binding) = resolver.current_module
.resolve_name_in_lexical_scope(name, ValueNS) {
if binding.is_import() {
err.span_note(binding.span.unwrap(), "constant imported here");
err.span_note(binding.span, "constant imported here");
}
}
err
@ -676,9 +675,7 @@ impl<T> ResolveResult<T> {
enum FallbackSuggestion {
NoSuggestion,
Field,
Method,
TraitItem,
StaticMethod(String),
TraitMethod(String),
}
@ -818,7 +815,6 @@ enum ParentLink<'a> {
pub struct ModuleS<'a> {
parent_link: ParentLink<'a>,
def: Option<Def>,
vis: ty::Visibility,
// If the module is an extern crate, `def` is root of the external crate and `extern_crate_id`
// is the NodeId of the local `extern crate` item (otherwise, `extern_crate_id` is None).
@ -833,7 +829,7 @@ pub struct ModuleS<'a> {
globs: RefCell<Vec<&'a ImportDirective<'a>>>,
// Used to memoize the traits in this module for faster searches through all traits in scope.
traits: RefCell<Option<Box<[&'a NameBinding<'a>]>>>,
traits: RefCell<Option<Box<[(Name, &'a NameBinding<'a>)]>>>,
// Whether this module is populated. If not populated, any attempt to
// access the children must be preceded with a
@ -849,12 +845,10 @@ impl<'a> ModuleS<'a> {
fn new(parent_link: ParentLink<'a>,
def: Option<Def>,
external: bool,
vis: ty::Visibility,
arenas: &'a ResolverArenas<'a>) -> Self {
ModuleS {
parent_link: parent_link,
def: def,
vis: vis,
extern_crate_id: None,
resolutions: RefCell::new(HashMap::new()),
unresolved_imports: RefCell::new(Vec::new()),
@ -895,7 +889,7 @@ impl<'a> ModuleS<'a> {
impl<'a> fmt::Debug for ModuleS<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}, {:?}", self.def, self.vis)
write!(f, "{:?}", self.def)
}
}
@ -903,7 +897,7 @@ impl<'a> fmt::Debug for ModuleS<'a> {
#[derive(Clone, Debug)]
pub struct NameBinding<'a> {
kind: NameBindingKind<'a>,
span: Option<Span>,
span: Span,
vis: ty::Visibility,
}
@ -923,14 +917,6 @@ enum NameBindingKind<'a> {
struct PrivacyError<'a>(Span, Name, &'a NameBinding<'a>);
impl<'a> NameBinding<'a> {
fn create_from_module(module: Module<'a>, span: Option<Span>) -> Self {
NameBinding {
kind: NameBindingKind::Module(module),
span: span,
vis: module.vis,
}
}
fn module(&self) -> Option<Module<'a>> {
match self.kind {
NameBindingKind::Module(module) => Some(module),
@ -1030,7 +1016,7 @@ pub struct Resolver<'a, 'tcx: 'a> {
graph_root: Module<'a>,
trait_item_map: FnvHashMap<(Name, DefId), DefId>,
trait_item_map: FnvHashMap<(Name, DefId), bool /* is static method? */>,
structs: FnvHashMap<DefId, Vec<Name>>,
@ -1135,10 +1121,19 @@ impl<'a> ResolverArenas<'a> {
}
}
#[derive(PartialEq)]
enum FallbackChecks {
Everything,
OnlyTraitAndStatics,
impl<'a, 'tcx> ty::NodeIdTree for Resolver<'a, 'tcx> {
fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool {
let ancestor = self.ast_map.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) {
Some(parent) => parent,
None => return false,
};
module = module_parent;
}
true
}
}
impl<'a, 'tcx> Resolver<'a, 'tcx> {
@ -1148,10 +1143,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
arenas: &'a ResolverArenas<'a>)
-> Resolver<'a, 'tcx> {
let root_def_id = ast_map.local_def_id(CRATE_NODE_ID);
let vis = ty::Visibility::Public;
let graph_root =
ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, vis, arenas);
ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, arenas);
let graph_root = arenas.alloc_module(graph_root);
let mut module_map = NodeMap();
module_map.insert(CRATE_NODE_ID, graph_root);
Resolver {
session: session,
@ -1182,7 +1178,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
freevars_seen: NodeMap(),
export_map: NodeMap(),
trait_map: NodeMap(),
module_map: NodeMap(),
module_map: module_map,
used_imports: HashSet::new(),
used_crates: HashSet::new(),
@ -1208,21 +1204,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
fn new_module(&self,
parent_link: ParentLink<'a>,
def: Option<Def>,
external: bool,
vis: ty::Visibility) -> Module<'a> {
self.arenas.alloc_module(ModuleS::new(parent_link, def, external, vis, self.arenas))
fn new_module(&self, parent_link: ParentLink<'a>, def: Option<Def>, external: bool)
-> Module<'a> {
self.arenas.alloc_module(ModuleS::new(parent_link, def, external, self.arenas))
}
fn new_extern_crate_module(&self,
parent_link: ParentLink<'a>,
def: Def,
vis: ty::Visibility,
local_node_id: NodeId)
fn new_extern_crate_module(&self, parent_link: ParentLink<'a>, def: Def, local_node_id: NodeId)
-> Module<'a> {
let mut module = ModuleS::new(parent_link, Some(def), false, vis, self.arenas);
let mut module = ModuleS::new(parent_link, Some(def), false, self.arenas);
module.extern_crate_id = Some(local_node_id);
self.arenas.modules.alloc(module)
}
@ -1262,14 +1251,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
self.glob_map.insert(directive.id, new_set);
}
fn get_trait_name(&self, did: DefId) -> Name {
if let Some(node_id) = self.ast_map.as_local_node_id(did) {
self.ast_map.expect_item(node_id).name
} else {
self.session.cstore.item_name(did)
}
}
/// Resolves the given module path from the given root `module_`.
fn resolve_module_path_from_root(&mut self,
module_: Module<'a>,
@ -1719,8 +1700,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
match self.resolve_crate_relative_path(prefix.span,
&prefix.segments,
TypeNS) {
Ok(def) =>
self.record_def(item.id, PathResolution::new(def, 0)),
Ok(binding) => {
let def = binding.def().unwrap();
self.record_def(item.id, PathResolution::new(def, 0));
}
Err(true) => self.record_def(item.id, err_path_resolution()),
Err(false) => {
resolve_error(self,
@ -1853,11 +1836,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
path_depth)));
// If it's a typedef, give a note
if let Def::TyAlias(did) = path_res.base_def {
if let Def::TyAlias(..) = path_res.base_def {
err.fileline_note(trait_path.span,
"`type` aliases cannot be used for traits");
if let Some(sp) = self.ast_map.span_if_local(did) {
err.span_note(sp, "type defined here");
let definition_site = {
let segments = &trait_path.segments;
if trait_path.global {
self.resolve_crate_relative_path(trait_path.span, segments, TypeNS)
} else {
self.resolve_module_relative_path(trait_path.span, segments, TypeNS)
}.map(|binding| binding.span).unwrap_or(codemap::DUMMY_SP)
};
if definition_site != codemap::DUMMY_SP {
err.span_note(definition_site, "type defined here");
}
}
err.emit();
@ -2583,8 +2576,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let mk_res = |def| PathResolution::new(def, path_depth);
if path.global {
let def = self.resolve_crate_relative_path(span, segments, namespace);
return def.map(mk_res);
let binding = self.resolve_crate_relative_path(span, segments, namespace);
return binding.map(|binding| mk_res(binding.def().unwrap()));
}
// Try to find a path to an item in a module.
@ -2620,9 +2613,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
let unqualified_def = resolve_identifier_with_fallback(self, false);
let def = self.resolve_module_relative_path(span, segments, namespace);
match (def, unqualified_def) {
(Ok(d), Some(ref ud)) if d == ud.def => {
let qualified_binding = self.resolve_module_relative_path(span, segments, namespace);
match (qualified_binding, unqualified_def) {
(Ok(binding), Some(ref ud)) if binding.def().unwrap() == ud.def => {
self.session
.add_lint(lint::builtin::UNUSED_QUALIFICATIONS,
id,
@ -2632,7 +2625,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
_ => {}
}
def.map(mk_res)
qualified_binding.map(|binding| mk_res(binding.def().unwrap()))
}
// Resolve a single identifier
@ -2743,7 +2736,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
span: Span,
segments: &[hir::PathSegment],
namespace: Namespace)
-> Result<Def, bool /* true if an error was reported */> {
-> Result<&'a NameBinding<'a>,
bool /* true if an error was reported */> {
let module_path = segments.split_last()
.unwrap()
.1
@ -2776,7 +2770,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let result = self.resolve_name_in_module(containing_module, name, namespace, false, true);
result.success().map(|binding| {
self.check_privacy(name, binding, span);
binding.def().unwrap()
binding
}).ok_or(false)
}
@ -2786,7 +2780,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
span: Span,
segments: &[hir::PathSegment],
namespace: Namespace)
-> Result<Def, bool /* true if an error was reported */> {
-> Result<&'a NameBinding<'a>,
bool /* true if an error was reported */> {
let module_path = segments.split_last()
.unwrap()
.1
@ -2826,7 +2821,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let result = self.resolve_name_in_module(containing_module, name, namespace, false, true);
result.success().map(|binding| {
self.check_privacy(name, binding, span);
binding.def().unwrap()
binding
}).ok_or(false)
}
@ -2840,13 +2835,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion {
fn extract_path_and_node_id(t: &Ty,
allow: FallbackChecks)
-> Option<(Path, NodeId, FallbackChecks)> {
fn extract_node_id(t: &Ty) -> Option<NodeId> {
match t.node {
TyPath(None, ref path) => Some((path.clone(), t.id, allow)),
TyPtr(ref mut_ty) => extract_path_and_node_id(&mut_ty.ty, OnlyTraitAndStatics),
TyRptr(_, ref mut_ty) => extract_path_and_node_id(&mut_ty.ty, allow),
TyPath(None, _) => Some(t.id),
TyRptr(_, 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.
@ -2854,51 +2846,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
fn get_module<'a, 'tcx>(this: &mut Resolver<'a, 'tcx>,
span: Span,
name_path: &[ast::Name])
-> Option<Module<'a>> {
let last_name = name_path.last().unwrap();
if name_path.len() == 1 {
match this.primitive_type_table.primitive_types.get(last_name) {
Some(_) => None,
None => this.current_module.resolve_name_in_lexical_scope(*last_name, TypeNS)
.and_then(NameBinding::module)
}
} else {
this.resolve_module_path(&name_path, UseLexicalScope, span).success()
}
}
fn is_static_method(this: &Resolver, did: DefId) -> bool {
if let Some(node_id) = this.ast_map.as_local_node_id(did) {
let sig = match this.ast_map.get(node_id) {
hir_map::NodeTraitItem(trait_item) => match trait_item.node {
hir::MethodTraitItem(ref sig, _) => sig,
_ => return false,
},
hir_map::NodeImplItem(impl_item) => match impl_item.node {
hir::ImplItemKind::Method(ref sig, _) => sig,
_ => return false,
},
_ => return false,
};
sig.explicit_self.node == hir::SelfStatic
} else {
this.session.cstore.is_static_method(did)
}
}
let (path, node_id, allowed) = match self.current_self_type {
Some(ref ty) => match extract_path_and_node_id(ty, Everything) {
Some(x) => x,
None => return NoSuggestion,
},
None => return NoSuggestion,
};
if allowed == Everything {
if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) {
// Look for a field with the same name in the current self_type.
match self.def_map.borrow().get(&node_id).map(|d| d.full_def()) {
Some(Def::Enum(did)) |
@ -2916,28 +2864,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
let name_path = path.segments.iter().map(|seg| seg.identifier.name).collect::<Vec<_>>();
// Look for a method in the current self type's impl module.
if let Some(module) = get_module(self, path.span, &name_path) {
if let Some(binding) = module.resolve_name_in_lexical_scope(name, ValueNS) {
if let Some(Def::Method(did)) = binding.def() {
if is_static_method(self, did) {
return StaticMethod(path_names_to_string(&path, 0));
}
if self.current_trait_ref.is_some() {
return TraitItem;
} else if allowed == Everything {
return Method;
}
}
}
}
// Look for a method in the current trait.
if let Some((trait_did, ref trait_ref)) = self.current_trait_ref {
if let Some(&did) = self.trait_item_map.get(&(name, trait_did)) {
if is_static_method(self, did) {
if let Some(&is_static_method) = self.trait_item_map.get(&(name, trait_did)) {
if is_static_method {
return TraitMethod(path_names_to_string(&trait_ref.path, 0));
} else {
return TraitItem;
@ -3092,10 +3022,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
Field => format!("`self.{}`", path_name),
Method |
TraitItem => format!("to call `self.{}`", path_name),
TraitMethod(path_str) |
StaticMethod(path_str) =>
TraitMethod(path_str) =>
format!("to call `{}::{}`", path_str, path_name),
};
@ -3241,20 +3169,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let mut traits = module.traits.borrow_mut();
if traits.is_none() {
let mut collected_traits = Vec::new();
module.for_each_child(|_, ns, binding| {
module.for_each_child(|name, ns, binding| {
if ns != TypeNS { return }
if let Some(Def::Trait(_)) = binding.def() {
collected_traits.push(binding);
collected_traits.push((name, binding));
}
});
*traits = Some(collected_traits.into_boxed_slice());
}
for binding in traits.as_ref().unwrap().iter() {
for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
let trait_def_id = binding.def().unwrap().def_id();
if self.trait_item_map.contains_key(&(name, trait_def_id)) {
add_trait_info(&mut found_traits, trait_def_id, name);
let trait_name = self.get_trait_name(trait_def_id);
self.record_use(trait_name, TypeNS, binding);
}
}
@ -3312,7 +3239,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
identifier: ident,
parameters: params,
};
let span = name_binding.span.unwrap_or(syntax::codemap::DUMMY_SP);
let span = name_binding.span;
let mut segms = path_segments.clone();
segms.push(segment);
let segms = HirVec::from_vec(segms);
@ -3433,7 +3360,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();
vis.is_accessible_from(node_id, &self.ast_map)
vis.is_accessible_from(node_id, self)
}
fn check_privacy(&mut self, name: Name, binding: &'a NameBinding<'a>, span: Span) {
@ -3466,7 +3393,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
binding: &NameBinding,
old_binding: &NameBinding) {
// Error on the second of two conflicting names
if old_binding.span.unwrap().lo > binding.span.unwrap().lo {
if old_binding.span.lo > binding.span.lo {
return self.report_conflict(parent, name, ns, old_binding, binding);
}
@ -3482,7 +3409,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
false => ("defined", "definition"),
};
let span = binding.span.unwrap();
let span = binding.span;
let msg = {
let kind = match (ns, old_binding.module()) {
(ValueNS, _) => "a value",
@ -3507,9 +3434,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
},
};
let span = old_binding.span.unwrap();
if span != codemap::DUMMY_SP {
err.span_note(span, &format!("previous {} of `{}` here", noun, name));
if old_binding.span != codemap::DUMMY_SP {
err.span_note(old_binding.span, &format!("previous {} of `{}` here", noun, name));
}
err.emit();
}

View File

@ -26,7 +26,7 @@ use rustc::hir::def::*;
use syntax::ast::{NodeId, Name};
use syntax::attr::AttrMetaMethods;
use syntax::codemap::Span;
use syntax::codemap::{Span, DUMMY_SP};
use syntax::util::lev_distance::find_best_match_for_name;
use std::cell::{Cell, RefCell};
@ -76,7 +76,7 @@ impl<'a> ImportDirective<'a> {
directive: self,
privacy_error: privacy_error,
},
span: Some(self.span),
span: self.span,
vis: self.vis,
}
}
@ -412,7 +412,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
if let SingleImport { target, .. } = e.import_directive.subclass {
let dummy_binding = self.resolver.arenas.alloc_name_binding(NameBinding {
kind: NameBindingKind::Def(Def::Err),
span: None,
span: DUMMY_SP,
vis: ty::Visibility::Public,
});
let dummy_binding = e.import_directive.import(dummy_binding, None);
@ -552,9 +552,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
_ => (),
}
let ast_map = self.resolver.ast_map;
match (&value_result, &type_result) {
(&Success(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis, ast_map) &&
(&Success(binding), _) if !binding.pseudo_vis()
.is_at_least(directive.vis, self.resolver) &&
self.resolver.is_accessible(binding.vis) => {
let msg = format!("`{}` is private, and cannot be reexported", source);
let note_msg = format!("consider marking `{}` as `pub` in the imported module",
@ -564,7 +564,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
.emit();
}
(_, &Success(binding)) if !binding.pseudo_vis().is_at_least(directive.vis, ast_map) &&
(_, &Success(binding)) if !binding.pseudo_vis()
.is_at_least(directive.vis, self.resolver) &&
self.resolver.is_accessible(binding.vis) => {
if binding.is_extern_crate() {
let msg = format!("extern crate `{}` is private, and cannot be reexported \
@ -691,12 +692,12 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind {
if ns == TypeNS && orig_binding.is_variant() &&
!orig_binding.vis.is_at_least(binding.vis, &self.resolver.ast_map) {
!orig_binding.vis.is_at_least(binding.vis, self.resolver) {
let msg = format!("variant `{}` is private, and cannot be reexported \
(error E0364), consider declaring its enum as `pub`",
name);
let lint = lint::builtin::PRIVATE_IN_PUBLIC;
self.resolver.session.add_lint(lint, directive.id, binding.span.unwrap(), msg);
self.resolver.session.add_lint(lint, directive.id, binding.span, msg);
}
}
}