Auto merge of #27451 - seanmonstar:use-groups-as, r=alexcrichton
An implementation of [RFC 1219](https://github.com/rust-lang/rfcs/pull/1219). The RFC is not merged yet, but once merged, this could be.
This commit is contained in:
commit
8856927f64
16 changed files with 170 additions and 34 deletions
|
@ -472,6 +472,7 @@ visibility
|
||||||
|
|
||||||
idents_or_self
|
idents_or_self
|
||||||
: ident_or_self { $$ = mk_node("IdentsOrSelf", 1, $1); }
|
: 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); }
|
| idents_or_self ',' ident_or_self { $$ = ext_node($1, 1, $3); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -859,11 +859,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
||||||
if let ast::ViewPathList(ref prefix, ref list) = vpath.node {
|
if let ast::ViewPathList(ref prefix, ref list) = vpath.node {
|
||||||
for pid in list {
|
for pid in list {
|
||||||
match pid.node {
|
match pid.node {
|
||||||
ast::PathListIdent { id, name } => {
|
ast::PathListIdent { id, name, .. } => {
|
||||||
debug!("privacy - ident item {}", id);
|
debug!("privacy - ident item {}", id);
|
||||||
self.check_path(pid.span, id, name.name);
|
self.check_path(pid.span, id, name.name);
|
||||||
}
|
}
|
||||||
ast::PathListMod { id } => {
|
ast::PathListMod { id, .. } => {
|
||||||
debug!("privacy - mod item {}", id);
|
debug!("privacy - mod item {}", id);
|
||||||
let name = prefix.segments.last().unwrap().identifier.name;
|
let name = prefix.segments.last().unwrap().identifier.name;
|
||||||
self.check_path(pid.span, id, name);
|
self.check_path(pid.span, id, name);
|
||||||
|
|
|
@ -341,10 +341,10 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
for source_item in source_items {
|
for source_item in source_items {
|
||||||
let (module_path, name) = match source_item.node {
|
let (module_path, name, rename) = match source_item.node {
|
||||||
PathListIdent { name, .. } =>
|
PathListIdent { name, rename, .. } =>
|
||||||
(module_path.clone(), name.name),
|
(module_path.clone(), name.name, rename.unwrap_or(name).name),
|
||||||
PathListMod { .. } => {
|
PathListMod { rename, .. } => {
|
||||||
let name = match module_path.last() {
|
let name = match module_path.last() {
|
||||||
Some(name) => *name,
|
Some(name) => *name,
|
||||||
None => {
|
None => {
|
||||||
|
@ -358,13 +358,14 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let module_path = module_path.split_last().unwrap().1;
|
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(
|
self.build_import_directive(
|
||||||
&**parent,
|
&**parent,
|
||||||
module_path,
|
module_path,
|
||||||
SingleImport(name, name),
|
SingleImport(rename, name),
|
||||||
source_item.span,
|
source_item.span,
|
||||||
source_item.node.id(),
|
source_item.node.id(),
|
||||||
is_public,
|
is_public,
|
||||||
|
|
|
@ -2366,7 +2366,7 @@ impl Clean<Vec<Item>> for doctree::Import {
|
||||||
let remaining = if !denied {
|
let remaining = if !denied {
|
||||||
let mut remaining = vec![];
|
let mut remaining = vec![];
|
||||||
for path in list {
|
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) => {
|
Some(items) => {
|
||||||
ret.extend(items);
|
ret.extend(items);
|
||||||
}
|
}
|
||||||
|
@ -2428,18 +2428,21 @@ pub struct ImportSource {
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub struct ViewListIdent {
|
pub struct ViewListIdent {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub rename: Option<String>,
|
||||||
pub source: Option<ast::DefId>,
|
pub source: Option<ast::DefId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clean<ViewListIdent> for ast::PathListItem {
|
impl Clean<ViewListIdent> for ast::PathListItem {
|
||||||
fn clean(&self, cx: &DocContext) -> ViewListIdent {
|
fn clean(&self, cx: &DocContext) -> ViewListIdent {
|
||||||
match self.node {
|
match self.node {
|
||||||
ast::PathListIdent { id, name } => ViewListIdent {
|
ast::PathListIdent { id, name, rename } => ViewListIdent {
|
||||||
name: name.clean(cx),
|
name: name.clean(cx),
|
||||||
|
rename: rename.map(|r| r.clean(cx)),
|
||||||
source: resolve_def(cx, id)
|
source: resolve_def(cx, id)
|
||||||
},
|
},
|
||||||
ast::PathListMod { id } => ViewListIdent {
|
ast::PathListMod { id, rename } => ViewListIdent {
|
||||||
name: "self".to_string(),
|
name: "self".to_string(),
|
||||||
|
rename: rename.map(|r| r.clean(cx)),
|
||||||
source: resolve_def(cx, id)
|
source: resolve_def(cx, id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -687,10 +687,15 @@ impl fmt::Display for clean::ViewListIdent {
|
||||||
match self.source {
|
match self.source {
|
||||||
Some(did) => {
|
Some(did) => {
|
||||||
let path = clean::Path::singleton(self.name.clone());
|
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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1658,14 +1658,29 @@ pub type Variant = Spanned<Variant_>;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
|
||||||
pub enum PathListItem_ {
|
pub enum PathListItem_ {
|
||||||
PathListIdent { name: Ident, id: NodeId },
|
PathListIdent {
|
||||||
PathListMod { id: NodeId }
|
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_ {
|
impl PathListItem_ {
|
||||||
pub fn id(&self) -> NodeId {
|
pub fn id(&self) -> NodeId {
|
||||||
match *self {
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1141,7 +1141,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||||
fn item_use_list(&self, sp: Span, vis: ast::Visibility,
|
fn item_use_list(&self, sp: Span, vis: ast::Visibility,
|
||||||
path: Vec<ast::Ident>, imports: &[ast::Ident]) -> P<ast::Item> {
|
path: Vec<ast::Ident>, imports: &[ast::Ident]) -> P<ast::Item> {
|
||||||
let imports = imports.iter().map(|id| {
|
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();
|
}).collect();
|
||||||
|
|
||||||
self.item_use(sp, vis,
|
self.item_use(sp, vis,
|
||||||
|
|
|
@ -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| {
|
path_list_idents.move_map(|path_list_ident| {
|
||||||
Spanned {
|
Spanned {
|
||||||
node: match path_list_ident.node {
|
node: match path_list_ident.node {
|
||||||
PathListIdent { id, name } =>
|
PathListIdent { id, name, rename } =>
|
||||||
PathListIdent {
|
PathListIdent {
|
||||||
id: fld.new_id(id),
|
id: fld.new_id(id),
|
||||||
|
rename: rename,
|
||||||
name: name
|
name: name
|
||||||
},
|
},
|
||||||
PathListMod { id } =>
|
PathListMod { id, rename } =>
|
||||||
PathListMod { id: fld.new_id(id) }
|
PathListMod {
|
||||||
|
id: fld.new_id(id),
|
||||||
|
rename: rename
|
||||||
|
}
|
||||||
},
|
},
|
||||||
span: fld.new_span(path_list_ident.span)
|
span: fld.new_span(path_list_ident.span)
|
||||||
}
|
}
|
||||||
|
|
|
@ -574,10 +574,12 @@ impl<'a> Parser<'a> {
|
||||||
pub fn parse_path_list_item(&mut self) -> PResult<ast::PathListItem> {
|
pub fn parse_path_list_item(&mut self) -> PResult<ast::PathListItem> {
|
||||||
let lo = self.span.lo;
|
let lo = self.span.lo;
|
||||||
let node = if try!(self.eat_keyword(keywords::SelfValue)) {
|
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 {
|
} else {
|
||||||
let ident = try!(self.parse_ident());
|
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;
|
let hi = self.last_span.hi;
|
||||||
Ok(spanned(lo, hi, node))
|
Ok(spanned(lo, hi, node))
|
||||||
|
@ -5117,8 +5119,8 @@ impl<'a> Parser<'a> {
|
||||||
-> PResult<P<Item>> {
|
-> PResult<P<Item>> {
|
||||||
|
|
||||||
let crate_name = try!(self.parse_ident());
|
let crate_name = try!(self.parse_ident());
|
||||||
let (maybe_path, ident) = if try!(self.eat_keyword(keywords::As)) {
|
let (maybe_path, ident) = if let Some(ident) = try!(self.parse_rename()) {
|
||||||
(Some(crate_name.name), try!(self.parse_ident()))
|
(Some(crate_name.name), ident)
|
||||||
} else {
|
} else {
|
||||||
(None, crate_name)
|
(None, crate_name)
|
||||||
};
|
};
|
||||||
|
@ -5779,12 +5781,18 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}).collect()
|
}).collect()
|
||||||
};
|
};
|
||||||
if try!(self.eat_keyword(keywords::As)) {
|
rename_to = try!(self.parse_rename()).unwrap_or(rename_to);
|
||||||
rename_to = try!(self.parse_ident())
|
|
||||||
}
|
|
||||||
Ok(P(spanned(lo, self.last_span.hi, ViewPathSimple(rename_to, path))))
|
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)) {
|
||||||
|
self.parse_ident().map(Some)
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses a source module as a crate. This is the main
|
/// Parses a source module as a crate. This is the main
|
||||||
/// entry point for the parser.
|
/// entry point for the parser.
|
||||||
pub fn parse_crate_mod(&mut self) -> PResult<Crate> {
|
pub fn parse_crate_mod(&mut self) -> PResult<Crate> {
|
||||||
|
|
|
@ -2646,11 +2646,23 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
try!(self.commasep(Inconsistent, &idents[..], |s, w| {
|
try!(self.commasep(Inconsistent, &idents[..], |s, w| {
|
||||||
match w.node {
|
match w.node {
|
||||||
ast::PathListIdent { name, .. } => {
|
ast::PathListIdent { name, rename, .. } => {
|
||||||
s.print_ident(name)
|
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 { .. } => {
|
ast::PathListMod { rename, .. } => {
|
||||||
word(&mut s.s, "self")
|
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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -233,10 +233,17 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
|
||||||
ViewPathList(ref prefix, ref list) => {
|
ViewPathList(ref prefix, ref list) => {
|
||||||
for id in list {
|
for id in list {
|
||||||
match id.node {
|
match id.node {
|
||||||
PathListIdent { name, .. } => {
|
PathListIdent { name, rename, .. } => {
|
||||||
visitor.visit_ident(id.span, name);
|
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 { .. } => ()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// 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 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 {
|
mod bar {
|
||||||
struct bar;
|
struct bar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod food {
|
||||||
|
pub use self::zug::baz::{self as bag, quux as beans};
|
||||||
|
|
||||||
|
mod zug {
|
||||||
|
pub mod baz {
|
||||||
|
pub struct quux;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
14
src/test/pretty/import-renames.rs
Normal file
14
src/test/pretty/import-renames.rs
Normal file
|
@ -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};
|
21
src/test/run-pass/import-rename.rs
Normal file
21
src/test/run-pass/import-rename.rs
Normal file
|
@ -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); }
|
|
@ -19,6 +19,9 @@ extern crate std as zed;
|
||||||
|
|
||||||
use std::str;
|
use std::str;
|
||||||
use zed::str as x;
|
use zed::str as x;
|
||||||
|
|
||||||
|
use std::io::{self, Error as IoError, Result as IoResult};
|
||||||
|
use std::error::{self as foo};
|
||||||
mod baz {
|
mod baz {
|
||||||
pub use std::str as x;
|
pub use std::str as x;
|
||||||
}
|
}
|
||||||
|
|
28
src/test/rustdoc/viewpath-rename.rs
Normal file
28
src/test/rustdoc/viewpath-rename.rs
Normal file
|
@ -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};
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue