提交 df0c6d93 编写于 作者: N Nick Cameron

save-analysis: emit names of items that a glob import actually imports.

There is also some work here to make resolve a bit more stable - it no longer overwrites a specific import with a glob import.

[breaking-change]

Import shadowing of single/list imports by globs is now forbidden. An interesting case is where a glob import imports a re-export (`pub use`) of a single import. This still counts as a single import for the purposes of shadowing .You can usually fix any bustage by re-ordering such imports. A single import may still shadow (override) a glob import or the prelude.
上级 bd3cf4c0
......@@ -146,6 +146,13 @@ pub fn get_impl_or_trait_item<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId)
tcx)
}
pub fn get_trait_name(cstore: &cstore::CStore, def: ast::DefId) -> ast::Name {
let cdata = cstore.get_crate_data(def.krate);
decoder::get_trait_name(cstore.intr.clone(),
&*cdata,
def.node)
}
pub fn get_trait_item_name_and_kind(cstore: &cstore::CStore, def: ast::DefId)
-> (ast::Name, def::TraitItemKind) {
let cdata = cstore.get_crate_data(def.krate);
......
......@@ -781,6 +781,14 @@ pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
impl_items
}
pub fn get_trait_name(intr: Rc<IdentInterner>,
cdata: Cmd,
id: ast::NodeId)
-> ast::Name {
let doc = lookup_item(id, cdata.data());
item_name(&*intr, doc)
}
pub fn get_trait_item_name_and_kind(intr: Rc<IdentInterner>,
cdata: Cmd,
id: ast::NodeId)
......
......@@ -105,6 +105,7 @@ pub struct CrateAnalysis<'tcx> {
pub ty_cx: ty::ctxt<'tcx>,
pub reachable: NodeSet,
pub name: String,
pub glob_map: Option<middle::resolve::GlobMap>,
}
#[deriving(Copy, PartialEq, Eq, Hash)]
......
......@@ -342,17 +342,24 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
let lang_items = time(time_passes, "language item collection", (), |_|
middle::lang_items::collect_language_items(krate, &sess));
let resolve::CrateMap {
let make_glob_map = match save_analysis(&sess) {
true => middle::resolve::MakeGlobMap::Yes,
false => middle::resolve::MakeGlobMap::No,
};
def_map,
freevars,
capture_mode_map,
export_map,
trait_map,
external_exports,
last_private_map
last_private_map,
glob_map,
} =
time(time_passes, "resolution", (),
|_| resolve::resolve_crate(&sess, &lang_items, krate));
|_| resolve::resolve_crate(&sess,
&lang_items,
krate,
make_glob_map));
// Discard MTWT tables that aren't required past resolution.
syntax::ext::mtwt::clear_tables();
......@@ -454,14 +461,19 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
public_items: public_items,
reachable: reachable_map,
name: name,
glob_map: glob_map,
}
}
fn save_analysis(sess: &Session) -> bool {
(sess.opts.debugging_opts & config::SAVE_ANALYSIS) != 0
}
pub fn phase_save_analysis(sess: &Session,
krate: &ast::Crate,
analysis: &ty::CrateAnalysis,
odir: &Option<Path>) {
if (sess.opts.debugging_opts & config::SAVE_ANALYSIS) == 0 {
if !save_analysis(sess) {
return;
}
time(sess.time_passes(), "save analysis", krate, |krate|
......
......@@ -123,7 +123,7 @@ fn test_env<F>(source_string: &str,
// run just enough stuff to build a tcx:
let lang_items = lang_items::collect_language_items(krate, &sess);
let resolve::CrateMap { def_map, freevars, capture_mode_map, .. } =
resolve::resolve_crate(&sess, &lang_items, krate);
resolve::resolve_crate(&sess, &ast_map, &lang_items, krate, resolve::MakeGlobMap::No);
let named_region_map = resolve_lifetime::krate(&sess, krate, &def_map);
let region_map = region::resolve_crate(&sess, krate);
let stability_index = stability::Index::build(krate);
......
......@@ -28,19 +28,19 @@
use syntax::codemap::{Span, DUMMY_SP};
use syntax::visit::{mod, Visitor};
struct UnusedImportCheckVisitor<'a, 'b:'a> {
resolver: &'a mut Resolver<'b>
struct UnusedImportCheckVisitor<'a, 'b:'a, 'tcx:'b> {
resolver: &'a mut Resolver<'b, 'tcx>
}
// Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver.
impl<'a, 'b> Deref<Resolver<'b>> for UnusedImportCheckVisitor<'a, 'b> {
fn deref<'c>(&'c self) -> &'c Resolver<'b> {
impl<'a, 'b, 'tcx> Deref<Resolver<'b, 'tcx>> for UnusedImportCheckVisitor<'a, 'b, 'tcx:'b> {
fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> {
&*self.resolver
}
}
impl<'a, 'b> DerefMut<Resolver<'b>> for UnusedImportCheckVisitor<'a, 'b> {
fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> {
impl<'a, 'b, 'tcx> DerefMut<Resolver<'b, 'tcx>> for UnusedImportCheckVisitor<'a, 'b, 'tcx:'b> {
fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> {
&mut *self.resolver
}
}
......@@ -104,7 +104,7 @@ fn finalize_import(&mut self, id: ast::NodeId, span: Span) {
}
}
impl<'a, 'b, 'v> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b> {
impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
fn visit_view_item(&mut self, vi: &ViewItem) {
// 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
......
此差异已折叠。
......@@ -1197,7 +1197,28 @@ fn visit_view_item(&mut self, i: &ast::ViewItem) {
self.cur_scope);
self.write_sub_paths_truncated(path);
}
ast::ViewPathGlob(ref path, _) => {
ast::ViewPathGlob(ref path, id) => {
// Make a comma-separated list of names of imported modules.
let mut name_string = String::new();
let glob_map = &self.analysis.glob_map;
let glob_map = glob_map.as_ref().unwrap();
if glob_map.contains_key(&id) {
let names = glob_map.index(&id);
for n in names.iter() {
if name_string.len() > 0 {
name_string.push_str(", ");
}
name_string.push_str(n.as_str());
}
}
let sub_span = self.span.sub_span_of_token(path.span,
token::BinOp(token::Star));
self.fmt.use_glob_str(path.span,
sub_span,
id,
name_string.as_slice(),
self.cur_scope);
self.write_sub_paths(path);
}
ast::ViewPathList(ref path, ref list, _) => {
......@@ -1482,6 +1503,7 @@ pub fn process_crate(sess: &Session,
return;
}
assert!(analysis.glob_map.is_some());
let cratename = match attr::find_crate_name(krate.attrs[]) {
Some(name) => name.get().to_string(),
None => {
......
......@@ -74,6 +74,7 @@ pub enum Row {
Impl,
Module,
UseAlias,
UseGlob,
ExternCrate,
Inheritance,
MethodCall,
......@@ -125,6 +126,7 @@ fn lookup_row(r: Row) -> (&'static str, Vec<&'static str>, bool, bool) {
UseAlias => ("use_alias",
vec!("id","refid","refidcrate","name","scopeid"),
true, true),
UseGlob => ("use_glob", vec!("id","value","scopeid"), true, true),
ExternCrate => ("extern_crate",
vec!("id","name","location","crate","scopeid"),
true, true),
......@@ -480,6 +482,18 @@ pub fn use_alias_str(&mut self,
svec!(id, mod_node, mod_crate, name, parent));
}
pub fn use_glob_str(&mut self,
span: Span,
sub_span: Option<Span>,
id: NodeId,
values: &str,
parent: NodeId) {
self.check_and_record(UseGlob,
span,
sub_span,
svec!(id, values, parent));
}
pub fn extern_crate_str(&mut self,
span: Span,
sub_span: Option<Span>,
......
......@@ -280,6 +280,19 @@ pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option<Span> {
}
}
pub fn sub_span_of_token(&self, span: Span, tok: Token) -> Option<Span> {
let mut toks = self.retokenise_span(span);
loop {
let next = toks.real_token();
if next.tok == token::Eof {
return None;
}
if next.tok == tok {
return self.make_sub_span(span, Some(next.sp));
}
}
}
pub fn sub_span_after_keyword(&self,
span: Span,
keyword: keywords::Keyword) -> Option<Span> {
......
......@@ -69,4 +69,3 @@ pub struct CrateTranslation {
pub crate_formats: dependency_format::Dependencies,
pub no_builtins: bool,
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册