AST: Make renames in imports closer to the source
Fix `unused_import_braces` lint false positive on `use prefix::{self as rename}`
This commit is contained in:
parent
c6c6cf9515
commit
b057c554ab
12 changed files with 53 additions and 40 deletions
|
@ -2047,8 +2047,8 @@ impl<'a> LoweringContext<'a> {
|
|||
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 {
|
||||
|
@ -2064,7 +2064,7 @@ impl<'a> LoweringContext<'a> {
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -377,11 +377,12 @@ impl UnusedImportBraces {
|
|||
// 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 => {
|
||||
|
|
|
@ -119,7 +119,8 @@ impl<'a> Resolver<'a> {
|
|||
.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;
|
||||
|
||||
|
@ -142,7 +143,7 @@ impl<'a> Resolver<'a> {
|
|||
// 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;
|
||||
}
|
||||
}
|
||||
|
@ -162,7 +163,7 @@ impl<'a> Resolver<'a> {
|
|||
ModuleKind::Block(..) => unreachable!(),
|
||||
};
|
||||
source.name = crate_name;
|
||||
if ident.name == keywords::DollarCrate.name() {
|
||||
if rename.is_none() {
|
||||
ident.name = crate_name;
|
||||
}
|
||||
|
||||
|
@ -206,8 +207,8 @@ impl<'a> Resolver<'a> {
|
|||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1342,7 +1342,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
|
|||
.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()
|
||||
|
|
|
@ -1880,18 +1880,29 @@ pub type Variant = Spanned<Variant_>;
|
|||
|
||||
#[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.
|
||||
|
|
|
@ -294,7 +294,7 @@ pub trait AstBuilder {
|
|||
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,
|
||||
|
@ -1159,16 +1159,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
}
|
||||
|
||||
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),
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -1178,7 +1177,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
(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();
|
||||
|
||||
|
|
|
@ -323,7 +323,8 @@ pub fn noop_fold_use_tree<T: Folder>(use_tree: UseTree, fld: &mut T) -> UseTree
|
|||
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))
|
||||
|
|
|
@ -7033,9 +7033,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
} 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()?)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -2949,13 +2949,12 @@ impl<'a> State<'a> {
|
|||
|
||||
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 => {
|
||||
|
|
|
@ -78,7 +78,7 @@ pub fn modify_for_testing(sess: &ParseSess,
|
|||
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 =
|
||||
|
@ -240,7 +240,8 @@ fn mk_reexport_mod(cx: &mut TestCtxt,
|
|||
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 {
|
||||
|
@ -502,7 +503,7 @@ fn mk_std(cx: &TestCtxt) -> P<ast::Item> {
|
|||
(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 {
|
||||
|
@ -590,13 +591,13 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<P<ast::Item>>) {
|
|||
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 {
|
||||
|
|
|
@ -354,10 +354,11 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
|
|||
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) => {
|
||||
|
|
|
@ -9,12 +9,12 @@
|
|||
// 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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue