diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2018-03-09 18:58:44 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2018-03-17 22:12:21 +0300 |
| commit | b057c554ab9c7615ebdb3c920010a164ec5bf3ed (patch) | |
| tree | 3fcc7c2945653152d55af9c48a498b9bb5384c94 /src | |
| parent | c6c6cf9515b330551b04f36025bc72e1288a96d9 (diff) | |
| download | rust-b057c554ab9c7615ebdb3c920010a164ec5bf3ed.tar.gz rust-b057c554ab9c7615ebdb3c920010a164ec5bf3ed.zip | |
AST: Make renames in imports closer to the source
Fix `unused_import_braces` lint false positive on `use prefix::{self as rename}`
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/hir/lowering.rs | 6 | ||||
| -rw-r--r-- | src/librustc_lint/unused.rs | 7 | ||||
| -rw-r--r-- | src/librustc_resolve/build_reduced_graph.rs | 11 | ||||
| -rw-r--r-- | src/librustc_save_analysis/dump_visitor.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/ast.rs | 17 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 7 | ||||
| -rw-r--r-- | src/libsyntax/test.rs | 13 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 7 | ||||
| -rw-r--r-- | src/test/compile-fail/lint-unnecessary-import-braces.rs | 4 |
12 files changed, 53 insertions, 40 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 41950d21c09..1e355bb30cb 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -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; } } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index d777f6f19b0..86f79c553c3 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -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 => { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 335064402c4..e6c8dfa8356 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -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); } } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index d92025a6787..b9b4186c818 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -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() diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 7ced6424824..fdb32486b5d 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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. diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index b88e064e7e5..97f784dd617 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -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(); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1a65fb7639a..146f580e04e 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -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)) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d1234d25764..7a432930490 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -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()?) } }; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 097c0fd16d0..18a758ba968 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -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 => { diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 39306229c82..9edfa767d31 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -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 { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 3bf9bfab245..bbf1fe124f1 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -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) => { diff --git a/src/test/compile-fail/lint-unnecessary-import-braces.rs b/src/test/compile-fail/lint-unnecessary-import-braces.rs index 1c0401ec56b..214a03c13f4 100644 --- a/src/test/compile-fail/lint-unnecessary-import-braces.rs +++ b/src/test/compile-fail/lint-unnecessary-import-braces.rs @@ -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; } |
