diff options
| author | Pietro Albini <pietro@pietroalbini.org> | 2017-09-26 23:04:00 +0200 |
|---|---|---|
| committer | Pietro Albini <pietro@pietroalbini.org> | 2017-11-30 13:10:26 +0100 |
| commit | 91ba8b42fcce0491fa8a1b95e4088bcabf9abf4a (patch) | |
| tree | 8816e095bc7a534e8d9ecbe542a5e640d35b6c2c /src/libsyntax | |
| parent | d6b010f98beae1591ea6e8e21008de97d6cf5be4 (diff) | |
| download | rust-91ba8b42fcce0491fa8a1b95e4088bcabf9abf4a.tar.gz rust-91ba8b42fcce0491fa8a1b95e4088bcabf9abf4a.zip | |
Implement RFC 2128 (use_nested_groups)
This commit adds support for nested groups inside `use` declarations,
such as `use foo::{bar, sub::{baz::Foo, *}};`.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 47 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 41 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 26 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 42 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 143 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 50 | ||||
| -rw-r--r-- | src/libsyntax/std_inject.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/test.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/util/node_count.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 43 |
10 files changed, 222 insertions, 206 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index ad9d5865120..3c1d6ea18f7 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -12,7 +12,6 @@ pub use self::TyParamBound::*; pub use self::UnsafeSource::*; -pub use self::ViewPath_::*; pub use self::PathParameters::*; pub use symbol::{Ident, Symbol as Name}; pub use util::ThinVec; @@ -1705,46 +1704,20 @@ pub struct Variant_ { pub type Variant = Spanned<Variant_>; -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub struct PathListItem_ { - pub name: Ident, - /// renamed in list, e.g. `use foo::{bar as baz};` - pub rename: Option<Ident>, - pub id: NodeId, -} - -pub type PathListItem = Spanned<PathListItem_>; - -pub type ViewPath = Spanned<ViewPath_>; - #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum ViewPath_ { - - /// `foo::bar::baz as quux` - /// - /// or just - /// - /// `foo::bar::baz` (with `as baz` implicitly on the right) - ViewPathSimple(Ident, Path), - - /// `foo::bar::*` - ViewPathGlob(Path), - - /// `foo::bar::{a,b,c}` - ViewPathList(Path, Vec<PathListItem>) +pub enum UseTreeKind { + Simple(Ident), + Glob, + Nested(Vec<(UseTree, NodeId)>), } -impl ViewPath_ { - pub fn path(&self) -> &Path { - match *self { - ViewPathSimple(_, ref path) | - ViewPathGlob (ref path) | - ViewPathList(ref path, _) => path - } - } +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub struct UseTree { + pub kind: UseTreeKind, + pub prefix: Path, + pub span: Span, } - /// 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. @@ -1913,7 +1886,7 @@ pub enum ItemKind { /// A use declaration (`use` or `pub use`) item. /// /// E.g. `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;` - Use(P<ViewPath>), + Use(P<UseTree>), /// A static item (`static` or `pub static`). /// /// E.g. `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";` diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 48d789372a0..25eef6db930 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -291,7 +291,7 @@ pub trait AstBuilder { -> ast::MetaItem; fn item_use(&self, sp: Span, - vis: ast::Visibility, vp: P<ast::ViewPath>) -> P<ast::Item>; + 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>; @@ -1142,7 +1142,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn item_use(&self, sp: Span, - vis: ast::Visibility, vp: P<ast::ViewPath>) -> P<ast::Item> { + vis: ast::Visibility, vp: P<ast::UseTree>) -> P<ast::Item> { P(ast::Item { id: ast::DUMMY_NODE_ID, ident: keywords::Invalid.ident(), @@ -1161,33 +1161,36 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn item_use_simple_(&self, sp: Span, vis: ast::Visibility, ident: ast::Ident, path: ast::Path) -> P<ast::Item> { - self.item_use(sp, vis, - P(respan(sp, - ast::ViewPathSimple(ident, - path)))) + self.item_use(sp, vis, P(ast::UseTree { + span: sp, + prefix: path, + kind: ast::UseTreeKind::Simple(ident), + })) } fn item_use_list(&self, sp: Span, vis: ast::Visibility, path: Vec<ast::Ident>, imports: &[ast::Ident]) -> P<ast::Item> { let imports = imports.iter().map(|id| { - let item = ast::PathListItem_ { - name: *id, - rename: None, - id: ast::DUMMY_NODE_ID, - }; - respan(sp, item) + (ast::UseTree { + span: sp, + prefix: self.path(sp, vec![*id]), + kind: ast::UseTreeKind::Simple(*id), + }, ast::DUMMY_NODE_ID) }).collect(); - self.item_use(sp, vis, - P(respan(sp, - ast::ViewPathList(self.path(sp, path), - imports)))) + self.item_use(sp, vis, P(ast::UseTree { + span: sp, + prefix: self.path(sp, path), + kind: ast::UseTreeKind::Nested(imports), + })) } fn item_use_glob(&self, sp: Span, vis: ast::Visibility, path: Vec<ast::Ident>) -> P<ast::Item> { - self.item_use(sp, vis, - P(respan(sp, - ast::ViewPathGlob(self.path(sp, path))))) + self.item_use(sp, vis, P(ast::UseTree { + span: sp, + prefix: self.path(sp, path), + kind: ast::UseTreeKind::Glob, + })) } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 89d1a3699e8..8507c9653db 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -428,6 +428,9 @@ declare_features! ( // In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`) (active, in_band_lifetimes, "1.23.0", Some(44524)), + + // Nested groups in `use` (RFC 2128) + (active, use_nested_groups, "1.23.0", Some(44494)), ); declare_features! ( @@ -1661,6 +1664,29 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { visit::walk_path(self, path); } + fn visit_use_tree(&mut self, use_tree: &'a ast::UseTree, id: NodeId, nested: bool) { + if nested { + match use_tree.kind { + ast::UseTreeKind::Simple(_) => { + if use_tree.prefix.segments.len() != 1 { + gate_feature_post!(&self, use_nested_groups, use_tree.span, + "paths in `use` groups are experimental"); + } + } + ast::UseTreeKind::Glob => { + gate_feature_post!(&self, use_nested_groups, use_tree.span, + "glob imports in `use` groups are experimental"); + } + ast::UseTreeKind::Nested(_) => { + gate_feature_post!(&self, use_nested_groups, use_tree.span, + "nested groups in `use` are experimental"); + } + } + } + + visit::walk_use_tree(self, use_tree, id); + } + fn visit_vis(&mut self, vis: &'a ast::Visibility) { if let ast::Visibility::Crate(span, ast::CrateSugar::JustCrate) = *vis { gate_feature_post!(&self, crate_visibility_modifier, span, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index cc63bffec48..1a92f057e5e 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -56,8 +56,8 @@ pub trait Folder : Sized { noop_fold_meta_item(meta_item, self) } - fn fold_view_path(&mut self, view_path: P<ViewPath>) -> P<ViewPath> { - noop_fold_view_path(view_path, self) + fn fold_use_tree(&mut self, use_tree: UseTree) -> UseTree { + noop_fold_use_tree(use_tree, self) } fn fold_foreign_item(&mut self, ni: ForeignItem) -> ForeignItem { @@ -310,30 +310,18 @@ pub fn noop_fold_meta_items<T: Folder>(meta_items: Vec<MetaItem>, fld: &mut T) - meta_items.move_map(|x| fld.fold_meta_item(x)) } -pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<ViewPath> { - view_path.map(|Spanned {node, span}| Spanned { - node: match node { - ViewPathSimple(ident, path) => { - ViewPathSimple(fld.fold_ident(ident), fld.fold_path(path)) - } - ViewPathGlob(path) => { - ViewPathGlob(fld.fold_path(path)) - } - ViewPathList(path, path_list_idents) => { - let path = fld.fold_path(path); - let path_list_idents = path_list_idents.move_map(|path_list_ident| Spanned { - node: PathListItem_ { - id: fld.new_id(path_list_ident.node.id), - rename: path_list_ident.node.rename.map(|ident| fld.fold_ident(ident)), - name: fld.fold_ident(path_list_ident.node.name), - }, - span: fld.new_span(path_list_ident.span) - }); - ViewPathList(path, path_list_idents) - } +pub fn noop_fold_use_tree<T: Folder>(use_tree: UseTree, fld: &mut T) -> UseTree { + 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::Glob => UseTreeKind::Glob, + UseTreeKind::Nested(items) => UseTreeKind::Nested(items.move_map(|(tree, id)| { + (fld.fold_use_tree(tree), fld.new_id(id)) + })), }, - span: fld.new_span(span) - }) + } } pub fn fold_attrs<T: Folder>(attrs: Vec<Attribute>, fld: &mut T) -> Vec<Attribute> { @@ -874,8 +862,8 @@ pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> { pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind { match i { ItemKind::ExternCrate(string) => ItemKind::ExternCrate(string), - ItemKind::Use(view_path) => { - ItemKind::Use(folder.fold_view_path(view_path)) + ItemKind::Use(use_tree) => { + ItemKind::Use(use_tree.map(|tree| folder.fold_use_tree(tree))) } ItemKind::Static(t, m, e) => { ItemKind::Static(folder.fold_ty(t), m, folder.fold_expr(e)) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 0f32d588b37..07956ecb5af 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -35,8 +35,8 @@ use ast::StrStyle; use ast::SelfKind; use ast::{TraitItem, TraitRef, TraitObjectSyntax}; use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds}; -use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{Visibility, WhereClause, CrateSugar}; +use ast::{UseTree, UseTreeKind}; use ast::{BinOpKind, UnOp}; use ast::{RangeEnd, RangeSyntax}; use {ast, attr}; @@ -1861,7 +1861,7 @@ impl<'a> Parser<'a> { loop { segments.push(self.parse_path_segment(style, enable_warning)?); - if self.is_import_coupler() || !self.eat(&token::ModSep) { + if self.is_import_coupler(false) || !self.eat(&token::ModSep) { return Ok(()); } } @@ -5964,7 +5964,7 @@ impl<'a> Parser<'a> { if self.eat_keyword(keywords::Use) { // USE ITEM - let item_ = ItemKind::Use(self.parse_view_path()?); + let item_ = ItemKind::Use(P(self.parse_use_tree(false)?)); self.expect(&token::Semi)?; let prev_span = self.prev_span; @@ -6407,74 +6407,101 @@ impl<'a> Parser<'a> { })) } - fn parse_path_list_items(&mut self) -> PResult<'a, Vec<ast::PathListItem>> { - self.parse_unspanned_seq(&token::OpenDelim(token::Brace), - &token::CloseDelim(token::Brace), - SeqSep::trailing_allowed(token::Comma), |this| { - let lo = this.span; - let ident = if this.eat_keyword(keywords::SelfValue) { - keywords::SelfValue.ident() - } else { - this.parse_ident()? - }; - let rename = this.parse_rename()?; - let node = ast::PathListItem_ { - name: ident, - rename, - id: ast::DUMMY_NODE_ID - }; - Ok(respan(lo.to(this.prev_span), node)) - }) + /// `{` or `::{` or `*` or `::*` + /// `::{` or `::*` (also `{` or `*` if unprefixed is true) + fn is_import_coupler(&mut self, unprefixed: bool) -> bool { + self.is_import_coupler_inner(&token::OpenDelim(token::Brace), unprefixed) || + self.is_import_coupler_inner(&token::BinOp(token::Star), unprefixed) } - /// `::{` or `::*` - fn is_import_coupler(&mut self) -> bool { - self.check(&token::ModSep) && - self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace) || - *t == token::BinOp(token::Star)) + fn is_import_coupler_inner(&mut self, token: &token::Token, unprefixed: bool) -> bool { + if self.check(&token::ModSep) { + self.look_ahead(1, |t| t == token) + } else if unprefixed { + self.check(token) + } else { + false + } } - /// Matches ViewPath: - /// MOD_SEP? non_global_path - /// MOD_SEP? non_global_path as IDENT - /// MOD_SEP? non_global_path MOD_SEP STAR - /// MOD_SEP? non_global_path MOD_SEP LBRACE item_seq RBRACE - /// MOD_SEP? LBRACE item_seq RBRACE - fn parse_view_path(&mut self) -> PResult<'a, P<ViewPath>> { + /// Parse UseTree + /// + /// USE_TREE = `*` | + /// `{` USE_TREE_LIST `}` | + /// PATH `::` `*` | + /// PATH `::` `{` USE_TREE_LIST `}` | + /// PATH [`as` IDENT] + fn parse_use_tree(&mut self, nested: bool) -> PResult<'a, UseTree> { let lo = self.span; - if self.check(&token::OpenDelim(token::Brace)) || self.check(&token::BinOp(token::Star)) || - self.is_import_coupler() { - // `{foo, bar}`, `::{foo, bar}`, `*`, or `::*`. - self.eat(&token::ModSep); - let prefix = ast::Path { - segments: vec![PathSegment::crate_root(lo)], - span: lo.to(self.span), - }; - let view_path_kind = if self.eat(&token::BinOp(token::Star)) { - ViewPathGlob(prefix) + + let mut prefix = ast::Path { + segments: vec![], + span: lo.to(self.span), + }; + + let kind = if self.is_import_coupler(true) { + // `use *;` or `use ::*;` or `use {...};` `use ::{...};` + + // Remove the first `::` + if self.eat(&token::ModSep) { + prefix.segments.push(PathSegment::crate_root(self.prev_span)); + } else if !nested { + prefix.segments.push(PathSegment::crate_root(self.span)); + } + + if self.eat(&token::BinOp(token::Star)) { + // `use *;` + UseTreeKind::Glob + } else if self.check(&token::OpenDelim(token::Brace)) { + // `use {...};` + UseTreeKind::Nested(self.parse_use_tree_list()?) } else { - ViewPathList(prefix, self.parse_path_list_items()?) - }; - Ok(P(respan(lo.to(self.span), view_path_kind))) + return self.unexpected(); + } } else { - let prefix = self.parse_path(PathStyle::Mod)?.default_to_global(); - if self.is_import_coupler() { - // `foo::bar::{a, b}` or `foo::bar::*` - self.bump(); - if self.check(&token::BinOp(token::Star)) { - self.bump(); - Ok(P(respan(lo.to(self.span), ViewPathGlob(prefix)))) + // `use path::...;` + let mut parsed = self.parse_path(PathStyle::Mod)?; + if !nested { + parsed = parsed.default_to_global(); + } + + prefix.segments.append(&mut parsed.segments); + prefix.span = prefix.span.to(parsed.span); + + if self.eat(&token::ModSep) { + if self.eat(&token::BinOp(token::Star)) { + // `use path::*;` + UseTreeKind::Glob + } else if self.check(&token::OpenDelim(token::Brace)) { + // `use path::{...};` + UseTreeKind::Nested(self.parse_use_tree_list()?) } else { - let items = self.parse_path_list_items()?; - Ok(P(respan(lo.to(self.span), ViewPathList(prefix, items)))) + return self.unexpected(); } } else { - // `foo::bar` or `foo::bar as baz` + // `use path::foo;` or `use path::foo as bar;` let rename = self.parse_rename()?. unwrap_or(prefix.segments.last().unwrap().identifier); - Ok(P(respan(lo.to(self.prev_span), ViewPathSimple(rename, prefix)))) + UseTreeKind::Simple(rename) } - } + }; + + Ok(UseTree { + span: lo.to(self.prev_span), + kind, + prefix, + }) + } + + /// Parse UseTreeKind::Nested(list) + /// + /// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`] + fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> { + self.parse_unspanned_seq(&token::OpenDelim(token::Brace), + &token::CloseDelim(token::Brace), + SeqSep::trailing_allowed(token::Comma), |this| { + Ok((this.parse_use_tree(true)?, ast::DUMMY_NODE_ID)) + }) } fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 38627b40544..a2d3ed4deb6 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1185,9 +1185,9 @@ impl<'a> State<'a> { self.end()?; // end inner head-block self.end()?; // end outer head-block } - ast::ItemKind::Use(ref vp) => { + ast::ItemKind::Use(ref tree) => { self.head(&visibility_qualified(&item.vis, "use"))?; - self.print_view_path(vp)?; + self.print_use_tree(tree)?; self.s.word(";")?; self.end()?; // end inner head-block self.end()?; // end outer head-block @@ -2918,45 +2918,39 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> io::Result<()> { - match vp.node { - ast::ViewPathSimple(ident, ref path) => { - self.print_path(path, false, 0, true)?; + pub fn print_use_tree(&mut self, tree: &ast::UseTree) -> io::Result<()> { + match tree.kind { + ast::UseTreeKind::Simple(ref ident) => { + self.print_path(&tree.prefix, false, 0, true)?; - if path.segments.last().unwrap().identifier.name != - ident.name { + if tree.prefix.segments.last().unwrap().identifier.name != ident.name { self.s.space()?; self.word_space("as")?; - self.print_ident(ident)?; + self.print_ident(*ident)?; } - - Ok(()) } - - ast::ViewPathGlob(ref path) => { - self.print_path(path, false, 0, true)?; - self.s.word("::*") + ast::UseTreeKind::Glob => { + if !tree.prefix.segments.is_empty() { + self.print_path(&tree.prefix, false, 0, true)?; + self.s.word("::")?; + } + self.s.word("*")?; } - - ast::ViewPathList(ref path, ref idents) => { - if path.segments.is_empty() { + ast::UseTreeKind::Nested(ref items) => { + if tree.prefix.segments.is_empty() { self.s.word("{")?; } else { - self.print_path(path, false, 0, true)?; + self.print_path(&tree.prefix, false, 0, true)?; self.s.word("::{")?; } - self.commasep(Inconsistent, &idents[..], |s, w| { - s.print_ident(w.node.name)?; - if let Some(ident) = w.node.rename { - s.s.space()?; - s.word_space("as")?; - s.print_ident(ident)?; - } - Ok(()) + self.commasep(Inconsistent, &items[..], |this, &(ref tree, _)| { + this.print_use_tree(tree) })?; - self.s.word("}") + self.s.word("}")?; } } + + Ok(()) } pub fn print_mutability(&mut self, diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 7aa94de9d3d..ae22230198f 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -13,7 +13,7 @@ use attr; use ext::hygiene::{Mark, SyntaxContext}; use symbol::{Symbol, keywords}; use syntax_pos::{DUMMY_SP, Span}; -use codemap::{self, ExpnInfo, NameAndSpan, MacroAttribute}; +use codemap::{ExpnInfo, NameAndSpan, MacroAttribute}; use ptr::P; use tokenstream::TokenStream; @@ -75,12 +75,16 @@ pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<Strin span, }], vis: ast::Visibility::Inherited, - node: ast::ItemKind::Use(P(codemap::dummy_spanned(ast::ViewPathGlob(ast::Path { - segments: ["{{root}}", name, "prelude", "v1"].into_iter().map(|name| { - ast::PathSegment::from_ident(ast::Ident::from_str(name), DUMMY_SP) - }).collect(), + node: ast::ItemKind::Use(P(ast::UseTree { + prefix: ast::Path { + segments: ["{{root}}", name, "prelude", "v1"].into_iter().map(|name| { + ast::PathSegment::from_ident(ast::Ident::from_str(name), DUMMY_SP) + }).collect(), + span, + }, + kind: ast::UseTreeKind::Glob, span, - })))), + })), id: ast::DUMMY_NODE_ID, ident: keywords::Invalid.ident(), span, diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 5a5a1ce3777..a4ac5826f99 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -455,9 +455,11 @@ fn mk_std(cx: &TestCtxt) -> P<ast::Item> { let id_test = Ident::from_str("test"); let sp = ignored_span(cx, DUMMY_SP); let (vi, vis, ident) = if cx.is_libtest { - (ast::ItemKind::Use( - P(nospan(ast::ViewPathSimple(id_test, - path_node(vec![id_test]))))), + (ast::ItemKind::Use(P(ast::UseTree { + span: DUMMY_SP, + prefix: path_node(vec![id_test]), + kind: ast::UseTreeKind::Simple(id_test), + })), ast::Visibility::Public, keywords::Invalid.ident()) } else { (ast::ItemKind::ExternCrate(None), ast::Visibility::Inherited, id_test) @@ -547,9 +549,11 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<P<ast::Item>>) { // building `use <ident> = __test::main` let reexport_ident = Ident::with_empty_ctxt(s); - let use_path = - nospan(ast::ViewPathSimple(reexport_ident, - path_node(vec![mod_ident, Ident::from_str("main")]))); + let use_path = ast::UseTree { + span: DUMMY_SP, + prefix: path_node(vec![mod_ident, Ident::from_str("main")]), + kind: ast::UseTreeKind::Simple(reexport_ident), + }; expander.fold_item(P(ast::Item { id: ast::DUMMY_NODE_ID, diff --git a/src/libsyntax/util/node_count.rs b/src/libsyntax/util/node_count.rs index 0a5d0c2e7fe..ac5642e53cf 100644 --- a/src/libsyntax/util/node_count.rs +++ b/src/libsyntax/util/node_count.rs @@ -133,9 +133,9 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_path(self, path) } - fn visit_path_list_item(&mut self, prefix: &Path, item: &PathListItem) { + fn visit_use_tree(&mut self, use_tree: &UseTree, id: NodeId, _nested: bool) { self.count += 1; - walk_path_list_item(self, prefix, item) + walk_use_tree(self, use_tree, id) } fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &PathParameters) { self.count += 1; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index c2e90f0bb13..9a06ed0ba02 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -120,8 +120,8 @@ pub trait Visitor<'ast>: Sized { fn visit_path(&mut self, path: &'ast Path, _id: NodeId) { walk_path(self, path) } - fn visit_path_list_item(&mut self, prefix: &'ast Path, item: &'ast PathListItem) { - walk_path_list_item(self, prefix, item) + fn visit_use_tree(&mut self, use_tree: &'ast UseTree, id: NodeId, _nested: bool) { + walk_use_tree(self, use_tree, id) } fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) { walk_path_segment(self, path_span, path_segment) @@ -236,22 +236,8 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { ItemKind::ExternCrate(opt_name) => { walk_opt_name(visitor, item.span, opt_name) } - ItemKind::Use(ref vp) => { - match vp.node { - ViewPathSimple(ident, ref path) => { - visitor.visit_ident(vp.span, ident); - visitor.visit_path(path, item.id); - } - ViewPathGlob(ref path) => { - visitor.visit_path(path, item.id); - } - ViewPathList(ref prefix, ref list) => { - visitor.visit_path(prefix, item.id); - for item in list { - visitor.visit_path_list_item(prefix, item) - } - } - } + ItemKind::Use(ref use_tree) => { + visitor.visit_use_tree(use_tree, item.id, false) } ItemKind::Static(ref typ, _, ref expr) | ItemKind::Const(ref typ, ref expr) => { @@ -381,11 +367,22 @@ pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) { } } -pub fn walk_path_list_item<'a, V: Visitor<'a>>(visitor: &mut V, - _prefix: &Path, - item: &'a PathListItem) { - visitor.visit_ident(item.span, item.node.name); - walk_opt_ident(visitor, item.span, item.node.rename); +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::Glob => {}, + UseTreeKind::Nested(ref use_trees) => { + for &(ref nested_tree, nested_id) in use_trees { + visitor.visit_use_tree(nested_tree, nested_id, true); + } + } + } } pub fn walk_path_segment<'a, V: Visitor<'a>>(visitor: &mut V, |
