about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSean McArthur <sean.monstar@gmail.com>2015-07-31 22:20:25 -0700
committerSean McArthur <sean.monstar@gmail.com>2015-08-08 11:54:15 -0700
commitcfcd449c4c36c68541c3389878e3262dac5e4746 (patch)
tree9b938e41ecaffb056741c5e55d7afd7d01a82d18
parentd03456183e85fe7bd465bbe7c8f67885a2528444 (diff)
downloadrust-cfcd449c4c36c68541c3389878e3262dac5e4746.tar.gz
rust-cfcd449c4c36c68541c3389878e3262dac5e4746.zip
rustc: rename multiple imports in a list
-rw-r--r--src/grammar/parser-lalr.y1
-rw-r--r--src/librustc_privacy/lib.rs4
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs13
-rw-r--r--src/librustdoc/clean/mod.rs9
-rw-r--r--src/librustdoc/html/format.rs9
-rw-r--r--src/libsyntax/ast.rs21
-rw-r--r--src/libsyntax/ext/build.rs2
-rw-r--r--src/libsyntax/fold.rs10
-rw-r--r--src/libsyntax/parse/parser.rs20
-rw-r--r--src/libsyntax/print/pprust.rs20
-rw-r--r--src/libsyntax/visit.rs11
-rw-r--r--src/test/compile-fail/unresolved-import.rs16
-rw-r--r--src/test/pretty/import-renames.rs14
-rw-r--r--src/test/run-pass/import-rename.rs21
-rw-r--r--src/test/run-pass/use.rs3
-rw-r--r--src/test/rustdoc/viewpath-rename.rs28
16 files changed, 169 insertions, 33 deletions
diff --git a/src/grammar/parser-lalr.y b/src/grammar/parser-lalr.y
index 1117f4d5ce8..abdef4aa5ac 100644
--- a/src/grammar/parser-lalr.y
+++ b/src/grammar/parser-lalr.y
@@ -472,6 +472,7 @@ visibility
 
 idents_or_self
 : ident_or_self                    { $$ = mk_node("IdentsOrSelf", 1, $1); }
+| ident_or_self AS ident           { $$ = mk_node("IdentsOrSelf", 2, $1, $3); }
 | idents_or_self ',' ident_or_self { $$ = ext_node($1, 1, $3); }
 ;
 
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 2ffb4cbd4bf..d49c5c5517b 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -862,11 +862,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
             if let ast::ViewPathList(ref prefix, ref list) = vpath.node {
                 for pid in list {
                     match pid.node {
-                        ast::PathListIdent { id, name } => {
+                        ast::PathListIdent { id, name, .. } => {
                             debug!("privacy - ident item {}", id);
                             self.check_path(pid.span, id, name.name);
                         }
-                        ast::PathListMod { id } => {
+                        ast::PathListMod { id, .. } => {
                             debug!("privacy - mod item {}", id);
                             let name = prefix.segments.last().unwrap().identifier.name;
                             self.check_path(pid.span, id, name);
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 656d6a36614..66177d3df91 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -341,10 +341,10 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                         }
 
                         for source_item in source_items {
-                            let (module_path, name) = match source_item.node {
-                                PathListIdent { name, .. } =>
-                                    (module_path.clone(), name.name),
-                                PathListMod { .. } => {
+                            let (module_path, name, rename) = match source_item.node {
+                                PathListIdent { name, rename, .. } =>
+                                    (module_path.clone(), name.name, rename.unwrap_or(name).name),
+                                PathListMod { rename, .. } => {
                                     let name = match module_path.last() {
                                         Some(name) => *name,
                                         None => {
@@ -358,13 +358,14 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                                         }
                                     };
                                     let module_path = module_path.split_last().unwrap().1;
-                                    (module_path.to_vec(), name)
+                                    let rename = rename.map(|n| n.name).unwrap_or(name);
+                                    (module_path.to_vec(), name, rename)
                                 }
                             };
                             self.build_import_directive(
                                 &**parent,
                                 module_path,
-                                SingleImport(name, name),
+                                SingleImport(rename, name),
                                 source_item.span,
                                 source_item.node.id(),
                                 is_public,
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 11a0e0eaa49..6431e688c8a 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2362,7 +2362,7 @@ impl Clean<Vec<Item>> for doctree::Import {
                 let remaining = if !denied {
                     let mut remaining = vec![];
                     for path in list {
-                        match inline::try_inline(cx, path.node.id(), None) {
+                        match inline::try_inline(cx, path.node.id(), path.node.rename()) {
                             Some(items) => {
                                 ret.extend(items);
                             }
@@ -2424,18 +2424,21 @@ pub struct ImportSource {
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct ViewListIdent {
     pub name: String,
+    pub rename: Option<String>,
     pub source: Option<ast::DefId>,
 }
 
 impl Clean<ViewListIdent> for ast::PathListItem {
     fn clean(&self, cx: &DocContext) -> ViewListIdent {
         match self.node {
-            ast::PathListIdent { id, name } => ViewListIdent {
+            ast::PathListIdent { id, name, rename } => ViewListIdent {
                 name: name.clean(cx),
+                rename: rename.map(|r| r.clean(cx)),
                 source: resolve_def(cx, id)
             },
-            ast::PathListMod { id } => ViewListIdent {
+            ast::PathListMod { id, rename } => ViewListIdent {
                 name: "self".to_string(),
+                rename: rename.map(|r| r.clean(cx)),
                 source: resolve_def(cx, id)
             }
         }
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 2255a2e969f..7d86a547e94 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -687,10 +687,15 @@ impl fmt::Display for clean::ViewListIdent {
         match self.source {
             Some(did) => {
                 let path = clean::Path::singleton(self.name.clone());
-                resolved_path(f, did, &path, false)
+                try!(resolved_path(f, did, &path, false));
             }
-            _ => write!(f, "{}", self.name),
+            _ => try!(write!(f, "{}", self.name)),
+        }
+
+        if let Some(ref name) = self.rename {
+            try!(write!(f, " as {}", name));
         }
+        Ok(())
     }
 }
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index db173d08308..555a249e368 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1656,14 +1656,29 @@ pub type Variant = Spanned<Variant_>;
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum PathListItem_ {
-    PathListIdent { name: Ident, id: NodeId },
-    PathListMod { id: NodeId }
+    PathListIdent {
+        name: Ident,
+        /// renamed in list, eg `use foo::{bar as baz};`
+        rename: Option<Ident>,
+        id: NodeId
+    },
+    PathListMod {
+        /// renamed in list, eg `use foo::{self as baz};`
+        rename: Option<Ident>,
+        id: NodeId
+    }
 }
 
 impl PathListItem_ {
     pub fn id(&self) -> NodeId {
         match *self {
-            PathListIdent { id, .. } | PathListMod { id } => id
+            PathListIdent { id, .. } | PathListMod { id, .. } => id
+        }
+    }
+
+    pub fn rename(&self) -> Option<Ident> {
+        match *self {
+            PathListIdent { rename, .. } | PathListMod { rename, .. } => rename
         }
     }
 }
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 2061165abd2..771ac85ef19 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -1141,7 +1141,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     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| {
-            respan(sp, ast::PathListIdent { name: *id, id: ast::DUMMY_NODE_ID })
+            respan(sp, ast::PathListIdent { name: *id, rename: None, id: ast::DUMMY_NODE_ID })
         }).collect();
 
         self.item_use(sp, vis,
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index dab6d41df30..418a2cf5a87 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -335,13 +335,17 @@ pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<
                              path_list_idents.move_map(|path_list_ident| {
                                 Spanned {
                                     node: match path_list_ident.node {
-                                        PathListIdent { id, name } =>
+                                        PathListIdent { id, name, rename } =>
                                             PathListIdent {
                                                 id: fld.new_id(id),
+                                                rename: rename,
                                                 name: name
                                             },
-                                        PathListMod { id } =>
-                                            PathListMod { id: fld.new_id(id) }
+                                        PathListMod { id, rename } =>
+                                            PathListMod {
+                                                id: fld.new_id(id),
+                                                rename: rename
+                                            }
                                     },
                                     span: fld.new_span(path_list_ident.span)
                                 }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index e7ab9a73c0f..981d6e1055a 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -573,10 +573,12 @@ impl<'a> Parser<'a> {
     pub fn parse_path_list_item(&mut self) -> PResult<ast::PathListItem> {
         let lo = self.span.lo;
         let node = if try!(self.eat_keyword(keywords::SelfValue)) {
-            ast::PathListMod { id: ast::DUMMY_NODE_ID }
+            let rename = try!(self.parse_rename());
+            ast::PathListMod { id: ast::DUMMY_NODE_ID, rename: rename }
         } else {
             let ident = try!(self.parse_ident());
-            ast::PathListIdent { name: ident, id: ast::DUMMY_NODE_ID }
+            let rename = try!(self.parse_rename());
+            ast::PathListIdent { name: ident, rename: rename, id: ast::DUMMY_NODE_ID }
         };
         let hi = self.last_span.hi;
         Ok(spanned(lo, hi, node))
@@ -5104,8 +5106,8 @@ impl<'a> Parser<'a> {
                                 -> PResult<P<Item>> {
 
         let crate_name = try!(self.parse_ident());
-        let (maybe_path, ident) = if try!(self.eat_keyword(keywords::As)) {
-            (Some(crate_name.name), try!(self.parse_ident()))
+        let (maybe_path, ident) = if let Some(ident) = try!(self.parse_rename()) {
+            (Some(crate_name.name), ident)
         } else {
             (None, crate_name)
         };
@@ -5766,10 +5768,16 @@ impl<'a> Parser<'a> {
                 }
             }).collect()
         };
+        rename_to = try!(self.parse_rename()).unwrap_or(rename_to);
+        Ok(P(spanned(lo, self.last_span.hi, ViewPathSimple(rename_to, path))))
+    }
+
+    fn parse_rename(&mut self) -> PResult<Option<Ident>> {
         if try!(self.eat_keyword(keywords::As)) {
-            rename_to = try!(self.parse_ident())
+            self.parse_ident().map(Some)
+        } else {
+            Ok(None)
         }
-        Ok(P(spanned(lo, self.last_span.hi, ViewPathSimple(rename_to, path))))
     }
 
     /// Parses a source module as a crate. This is the main
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index f0973e0ba6e..1de922a0428 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -2643,11 +2643,23 @@ impl<'a> State<'a> {
                 }
                 try!(self.commasep(Inconsistent, &idents[..], |s, w| {
                     match w.node {
-                        ast::PathListIdent { name, .. } => {
-                            s.print_ident(name)
+                        ast::PathListIdent { name, rename, .. } => {
+                            try!(s.print_ident(name));
+                            if let Some(ident) = rename {
+                                try!(space(&mut s.s));
+                                try!(s.word_space("as"));
+                                try!(s.print_ident(ident));
+                            }
+                            Ok(())
                         },
-                        ast::PathListMod { .. } => {
-                            word(&mut s.s, "self")
+                        ast::PathListMod { rename, .. } => {
+                            try!(word(&mut s.s, "self"));
+                            if let Some(ident) = rename {
+                                try!(space(&mut s.s));
+                                try!(s.word_space("as"));
+                                try!(s.print_ident(ident));
+                            }
+                            Ok(())
                         }
                     }
                 }));
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 649052d123c..27d95cbcf5b 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -233,10 +233,17 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
                 ViewPathList(ref prefix, ref list) => {
                     for id in list {
                         match id.node {
-                            PathListIdent { name, .. } => {
+                            PathListIdent { name, rename, .. } => {
                                 visitor.visit_ident(id.span, name);
+                                if let Some(ident) = rename {
+                                    visitor.visit_ident(id.span, ident);
+                                }
+                            }
+                            PathListMod { rename, .. } => {
+                                if let Some(ident) = rename {
+                                    visitor.visit_ident(id.span, ident);
+                                }
                             }
-                            PathListMod { .. } => ()
                         }
                     }
 
diff --git a/src/test/compile-fail/unresolved-import.rs b/src/test/compile-fail/unresolved-import.rs
index 7da7b364bda..5edcf1d99a0 100644
--- a/src/test/compile-fail/unresolved-import.rs
+++ b/src/test/compile-fail/unresolved-import.rs
@@ -1,4 +1,4 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -12,6 +12,20 @@ use foo::bar; //~ ERROR unresolved import `foo::bar`. Maybe a missing `extern cr
 
 use bar::baz as x; //~ ERROR unresolved import `bar::baz`. There is no `baz` in `bar`
 
+use food::baz; //~ ERROR unresolved import `food::baz`. There is no `baz` in `food`
+
+use food::{quux as beans}; //~ ERROR unresolved import `food::quux`. There is no `quux` in `food`
+
 mod bar {
     struct bar;
 }
+
+mod food {
+    pub use self::zug::baz::{self as bag, quux as beans};
+
+    mod zug {
+        pub mod baz {
+            pub struct quux;
+        }
+    }
+}
diff --git a/src/test/pretty/import-renames.rs b/src/test/pretty/import-renames.rs
new file mode 100644
index 00000000000..47a878711ba
--- /dev/null
+++ b/src/test/pretty/import-renames.rs
@@ -0,0 +1,14 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// pp-exact
+
+use std::io::{self, Error as IoError};
+use std::net::{self as stdnet, TcpStream};
diff --git a/src/test/run-pass/import-rename.rs b/src/test/run-pass/import-rename.rs
new file mode 100644
index 00000000000..f293c284f94
--- /dev/null
+++ b/src/test/run-pass/import-rename.rs
@@ -0,0 +1,21 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use foo::{x, y as fooy};
+use Maybe::{Yes as MaybeYes};
+
+pub enum Maybe { Yes, No }
+mod foo {
+    use super::Maybe::{self as MaybeFoo};
+    pub fn x(a: MaybeFoo) {}
+    pub fn y(a: i32) { println!("{}", a); }
+}
+
+pub fn main() { x(MaybeYes); fooy(10); }
diff --git a/src/test/run-pass/use.rs b/src/test/run-pass/use.rs
index 592d17922e1..09a3849b915 100644
--- a/src/test/run-pass/use.rs
+++ b/src/test/run-pass/use.rs
@@ -19,6 +19,9 @@ extern crate std as zed;
 
 use std::str;
 use zed::str as x;
+
+use std::io::{self, Error as IoError, Result as IoResult};
+use std::error::{self as foo};
 mod baz {
     pub use std::str as x;
 }
diff --git a/src/test/rustdoc/viewpath-rename.rs b/src/test/rustdoc/viewpath-rename.rs
new file mode 100644
index 00000000000..ccc0acab7f3
--- /dev/null
+++ b/src/test/rustdoc/viewpath-rename.rs
@@ -0,0 +1,28 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+pub mod io {
+    pub trait Reader { fn dummy(&self) { } }
+}
+
+pub enum Maybe<A> {
+    Just(A),
+    Nothing
+}
+
+// @has foo/prelude/index.html
+pub mod prelude {
+    // @has foo/prelude/index.html '//code' 'pub use io::{self as FooIo, Reader as FooReader}'
+    #[doc(no_inline)] pub use io::{self as FooIo, Reader as FooReader};
+    // @has foo/prelude/index.html '//code' 'pub use Maybe::{self, Just as MaybeJust, Nothing}'
+    #[doc(no_inline)] pub use Maybe::{self, Just as MaybeJust, Nothing};
+}