Fix `unused_import_braces` lint false positive on `use prefix::{self as rename}`
let path = &tree.prefix;
match tree.kind {
- UseTreeKind::Simple(ident) => {
- *name = ident.name;
+ UseTreeKind::Simple(rename) => {
+ *name = tree.ident().name;
// First apply the prefix to the path
let mut path = Path {
if path.segments.len() > 1 &&
path.segments.last().unwrap().identifier.name == keywords::SelfValue.name() {
let _ = path.segments.pop();
- if ident.name == keywords::SelfValue.name() {
+ if rename.is_none() {
*name = path.segments.last().unwrap().identifier.name;
}
}
// Trigger the lint if the nested item is a non-self single item
let node_ident;
match items[0].0.kind {
- ast::UseTreeKind::Simple(ident) => {
- if ident.name == keywords::SelfValue.name() {
+ ast::UseTreeKind::Simple(rename) => {
+ let orig_ident = items[0].0.prefix.segments.last().unwrap().identifier;
+ if orig_ident.name == keywords::SelfValue.name() {
return;
} else {
- node_ident = ident;
+ node_ident = rename.unwrap_or(orig_ident);
}
}
ast::UseTreeKind::Glob => {
.collect();
match use_tree.kind {
- ast::UseTreeKind::Simple(mut ident) => {
+ ast::UseTreeKind::Simple(rename) => {
+ let mut ident = use_tree.ident();
let mut source = module_path.pop().unwrap().node;
let mut type_ns_only = false;
// Replace `use foo::self;` with `use foo;`
let _ = module_path.pop();
source = last_segment.node;
- if ident.name == keywords::SelfValue.name() {
+ if rename.is_none() {
ident = last_segment.node;
}
}
ModuleKind::Block(..) => unreachable!(),
};
source.name = crate_name;
- if ident.name == keywords::DollarCrate.name() {
+ if rename.is_none() {
ident.name = crate_name;
}
// Ensure there is at most one `self` in the list
let self_spans = items.iter().filter_map(|&(ref use_tree, _)| {
- if let ast::UseTreeKind::Simple(ident) = use_tree.kind {
- if ident.name == keywords::SelfValue.name() {
+ if let ast::UseTreeKind::Simple(..) = use_tree.kind {
+ if use_tree.ident().name == keywords::SelfValue.name() {
return Some(use_tree.span);
}
}
.map(::id_from_def_id);
match use_tree.kind {
- ast::UseTreeKind::Simple(ident) => {
+ ast::UseTreeKind::Simple(..) => {
+ let ident = use_tree.ident();
let path = ast::Path {
segments: prefix.segments
.iter()
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum UseTreeKind {
- Simple(Ident),
- Glob,
+ Simple(Option<Ident>),
Nested(Vec<(UseTree, NodeId)>),
+ Glob,
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct UseTree {
- pub kind: UseTreeKind,
pub prefix: Path,
+ pub kind: UseTreeKind,
pub span: Span,
}
+impl UseTree {
+ pub fn ident(&self) -> Ident {
+ match self.kind {
+ UseTreeKind::Simple(Some(rename)) => rename,
+ UseTreeKind::Simple(None) =>
+ self.prefix.segments.last().expect("empty prefix in a simple import").identifier,
+ _ => panic!("`UseTree::ident` can only be used on a simple import"),
+ }
+ }
+}
+
/// Distinguishes between Attributes that decorate items and Attributes that
/// are contained as statements within items. These two cases need to be
/// distinguished for pretty-printing.
vis: ast::Visibility, vp: P<ast::UseTree>) -> P<ast::Item>;
fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P<ast::Item>;
fn item_use_simple_(&self, sp: Span, vis: ast::Visibility,
- ident: ast::Ident, path: ast::Path) -> P<ast::Item>;
+ ident: Option<ast::Ident>, path: ast::Path) -> P<ast::Item>;
fn item_use_list(&self, sp: Span, vis: ast::Visibility,
path: Vec<ast::Ident>, imports: &[ast::Ident]) -> P<ast::Item>;
fn item_use_glob(&self, sp: Span,
}
fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P<ast::Item> {
- let last = path.segments.last().unwrap().identifier;
- self.item_use_simple_(sp, vis, last, path)
+ self.item_use_simple_(sp, vis, None, path)
}
fn item_use_simple_(&self, sp: Span, vis: ast::Visibility,
- ident: ast::Ident, path: ast::Path) -> P<ast::Item> {
+ rename: Option<ast::Ident>, path: ast::Path) -> P<ast::Item> {
self.item_use(sp, vis, P(ast::UseTree {
span: sp,
prefix: path,
- kind: ast::UseTreeKind::Simple(ident),
+ kind: ast::UseTreeKind::Simple(rename),
}))
}
(ast::UseTree {
span: sp,
prefix: self.path(sp, vec![*id]),
- kind: ast::UseTreeKind::Simple(*id),
+ kind: ast::UseTreeKind::Simple(None),
}, ast::DUMMY_NODE_ID)
}).collect();
span: fld.new_span(use_tree.span),
prefix: fld.fold_path(use_tree.prefix),
kind: match use_tree.kind {
- UseTreeKind::Simple(ident) => UseTreeKind::Simple(fld.fold_ident(ident)),
+ UseTreeKind::Simple(rename) =>
+ UseTreeKind::Simple(rename.map(|ident| fld.fold_ident(ident))),
UseTreeKind::Glob => UseTreeKind::Glob,
UseTreeKind::Nested(items) => UseTreeKind::Nested(items.move_map(|(tree, id)| {
(fld.fold_use_tree(tree), fld.new_id(id))
}
} else {
// `use path::foo;` or `use path::foo as bar;`
- let rename = self.parse_rename()?.
- unwrap_or(prefix.segments.last().unwrap().identifier);
- UseTreeKind::Simple(rename)
+ UseTreeKind::Simple(self.parse_rename()?)
}
};
pub fn print_use_tree(&mut self, tree: &ast::UseTree) -> io::Result<()> {
match tree.kind {
- ast::UseTreeKind::Simple(ref ident) => {
+ ast::UseTreeKind::Simple(rename) => {
self.print_path(&tree.prefix, false, 0, true)?;
-
- if tree.prefix.segments.last().unwrap().identifier.name != ident.name {
+ if let Some(rename) = rename {
self.s.space()?;
self.word_space("as")?;
- self.print_ident(*ident)?;
+ self.print_ident(rename)?;
}
}
ast::UseTreeKind::Glob => {
span_diagnostic: &errors::Handler,
features: &Features) -> ast::Crate {
// Check for #[reexport_test_harness_main = "some_name"] which
- // creates a `use some_name = __test::main;`. This needs to be
+ // creates a `use __test::main as some_name;`. This needs to be
// unconditional, so that the attribute is still marked as used in
// non-test builds.
let reexport_test_harness_main =
cx.ext_cx.path(DUMMY_SP, vec![super_, r]))
}).chain(tested_submods.into_iter().map(|(r, sym)| {
let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]);
- cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public), r, path)
+ cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public),
+ Some(r), path)
})).collect();
let reexport_mod = ast::Mod {
(ast::ItemKind::Use(P(ast::UseTree {
span: DUMMY_SP,
prefix: path_node(vec![id_test]),
- kind: ast::UseTreeKind::Simple(id_test),
+ kind: ast::UseTreeKind::Simple(None),
})),
ast::VisibilityKind::Public, keywords::Invalid.ident())
} else {
tokens: None,
})).pop().unwrap();
let reexport = cx.reexport_test_harness_main.map(|s| {
- // building `use <ident> = __test::main`
- let reexport_ident = Ident::with_empty_ctxt(s);
+ // building `use __test::main as <ident>;`
+ let rename = Ident::with_empty_ctxt(s);
let use_path = ast::UseTree {
span: DUMMY_SP,
prefix: path_node(vec![mod_ident, Ident::from_str("main")]),
- kind: ast::UseTreeKind::Simple(reexport_ident),
+ kind: ast::UseTreeKind::Simple(Some(rename)),
};
expander.fold_item(P(ast::Item {
visitor: &mut V, use_tree: &'a UseTree, id: NodeId,
) {
visitor.visit_path(&use_tree.prefix, id);
-
match use_tree.kind {
- UseTreeKind::Simple(ident) => {
- visitor.visit_ident(use_tree.span, ident);
+ UseTreeKind::Simple(rename) => {
+ if let Some(rename) = rename {
+ visitor.visit_ident(use_tree.span, rename);
+ }
}
UseTreeKind::Glob => {},
UseTreeKind::Nested(ref use_trees) => {
// except according to those terms.
#![deny(unused_import_braces)]
-#![allow(dead_code)]
-#![allow(unused_imports)]
use test::{A}; //~ ERROR braces around A is unnecessary
mod test {
+ use test::{self}; // OK
+ use test::{self as rename}; // OK
pub struct A;
}