Skip to content

Implement new mod import sugar #15808

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from Jul 20, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 22 additions & 14 deletions src/librustc/middle/privacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -901,21 +901,29 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
ast::ViewItemUse(ref vpath) => {
match vpath.node {
ast::ViewPathSimple(..) | ast::ViewPathGlob(..) => {}
ast::ViewPathList(_, ref list, _) => {
ast::ViewPathList(ref prefix, ref list, _) => {
for pid in list.iter() {
debug!("privacy - list {}", pid.node.id);
let seg = ast::PathSegment {
identifier: pid.node.name,
lifetimes: Vec::new(),
types: OwnedSlice::empty(),
};
let segs = vec!(seg);
let path = ast::Path {
global: false,
span: pid.span,
segments: segs,
};
self.check_path(pid.span, pid.node.id, &path);
match pid.node {
ast::PathListIdent { id, name } => {
debug!("privacy - ident item {}", id);
let seg = ast::PathSegment {
identifier: name,
lifetimes: Vec::new(),
types: OwnedSlice::empty(),
};
let segs = vec![seg];
let path = ast::Path {
global: false,
span: pid.span,
segments: segs,
};
self.check_path(pid.span, id, &path);
}
ast::PathListMod { id } => {
debug!("privacy - mod item {}", id);
self.check_path(pid.span, id, prefix);
}
}
}
}
}
Expand Down
80 changes: 55 additions & 25 deletions src/librustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1455,29 +1455,20 @@ impl<'a> Resolver<'a> {
// Extract and intern the module part of the path. For
// globs and lists, the path is found directly in the AST;
// for simple paths we have to munge the path a little.

let mut module_path = Vec::new();
match view_path.node {
let module_path = match view_path.node {
ViewPathSimple(_, ref full_path, _) => {
let path_len = full_path.segments.len();
assert!(path_len != 0);

for (i, segment) in full_path.segments
.iter()
.enumerate() {
if i != path_len - 1 {
module_path.push(segment.identifier)
}
}
full_path.segments
.as_slice().init()
.iter().map(|ident| ident.identifier)
.collect()
}

ViewPathGlob(ref module_ident_path, _) |
ViewPathList(ref module_ident_path, _, _) => {
for segment in module_ident_path.segments.iter() {
module_path.push(segment.identifier)
}
module_ident_path.segments
.iter().map(|ident| ident.identifier).collect()
}
}
};

// Build up the import directives.
let module_ = parent.module();
Expand All @@ -1486,6 +1477,11 @@ impl<'a> Resolver<'a> {
ViewPathSimple(binding, ref full_path, id) => {
let source_ident =
full_path.segments.last().unwrap().identifier;
if token::get_ident(source_ident).get() == "mod" {
self.resolve_error(view_path.span,
"`mod` imports are only allowed within a { } list");
}

let subclass = SingleImport(binding,
source_ident);
self.build_import_directive(&*module_,
Expand All @@ -1495,16 +1491,50 @@ impl<'a> Resolver<'a> {
id,
is_public);
}
ViewPathList(_, ref source_idents, _) => {
for source_ident in source_idents.iter() {
let name = source_ident.node.name;
ViewPathList(_, ref source_items, _) => {
// Make sure there's at most one `mod` import in the list.
let mod_spans = source_items.iter().filter_map(|item| match item.node {
PathListMod { .. } => Some(item.span),
_ => None
}).collect::<Vec<Span>>();
match mod_spans.as_slice() {
[first, second, ..other] => {
self.resolve_error(first,
"`mod` import can only appear once in the list");
self.session.span_note(second,
"another `mod` import appears here");
for &other_span in other.iter() {
self.session.span_note(other_span,
"another `mod` import appears here");
}
},
[_] | [] => ()
}

for source_item in source_items.iter() {
let (module_path, name) = match source_item.node {
PathListIdent { name, .. } =>
(module_path.clone(), name),
PathListMod { .. } => {
let name = match module_path.last() {
Some(ident) => ident.clone(),
None => {
self.resolve_error(source_item.span,
"`mod` import can only appear in an import list \
with a non-empty prefix");
continue;
}
};
let module_path = module_path.as_slice().init();
(Vec::from_slice(module_path), name)
}
};
self.build_import_directive(
&*module_,
module_path.clone(),
module_path,
SingleImport(name, name),
source_ident.span,
source_ident.node.id,
is_public);
source_item.span,
source_item.node.id(), is_public);
}
}
ViewPathGlob(_, id) => {
Expand Down Expand Up @@ -5492,7 +5522,7 @@ impl<'a> Resolver<'a> {
ViewPathSimple(_, _, id) => self.finalize_import(id, p.span),
ViewPathList(_, ref list, _) => {
for i in list.iter() {
self.finalize_import(i.node.id, i.span);
self.finalize_import(i.node.id(), i.span);
}
},
ViewPathGlob(_, id) => {
Expand Down
25 changes: 16 additions & 9 deletions src/librustc/middle/save/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1120,16 +1120,23 @@ impl<'l> Visitor<DxrVisitorEnv> for DxrVisitor<'l> {
}
ast::ViewPathList(ref path, ref list, _) => {
for plid in list.iter() {
match self.lookup_type_ref(plid.node.id) {
Some(id) => match self.lookup_def_kind(plid.node.id, plid.span) {
Some(kind) => self.fmt.ref_str(kind,
plid.span,
Some(plid.span),
id,
e.cur_scope),
None => (),
match plid.node {
ast::PathListIdent { id, .. } => {
match self.lookup_type_ref(id) {
Some(def_id) =>
match self.lookup_def_kind(id, plid.span) {
Some(kind) => {
self.fmt.ref_str(
kind, plid.span,
Some(plid.span),
def_id, e.cur_scope);
}
None => ()
},
None => ()
}
},
None => ()
ast::PathListMod { .. } => ()
}
}

Expand Down
18 changes: 12 additions & 6 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1779,13 +1779,13 @@ impl Clean<Vec<Item>> for ast::ViewItem {
// to keep any non-inlineable reexports so they can be
// listed in the documentation.
let remaining = list.iter().filter(|path| {
match inline::try_inline(path.node.id) {
match inline::try_inline(path.node.id()) {
Some(items) => {
ret.extend(items.move_iter()); false
}
None => true,
}
}).map(|a| a.clone()).collect::<Vec<ast::PathListIdent>>();
}).map(|a| a.clone()).collect::<Vec<ast::PathListItem>>();
if remaining.len() > 0 {
let path = ast::ViewPathList(a.clone(),
remaining,
Expand Down Expand Up @@ -1868,11 +1868,17 @@ pub struct ViewListIdent {
pub source: Option<ast::DefId>,
}

impl Clean<ViewListIdent> for ast::PathListIdent {
impl Clean<ViewListIdent> for ast::PathListItem {
fn clean(&self) -> ViewListIdent {
ViewListIdent {
name: self.node.name.clean(),
source: resolve_def(self.node.id),
match self.node {
ast::PathListIdent { id, name } => ViewListIdent {
name: name.clean(),
source: resolve_def(id)
},
ast::PathListMod { id } => ViewListIdent {
name: "mod".to_string(),
source: resolve_def(id)
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/visit_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ impl<'a> RustdocVisitor<'a> {
ast::ViewPathList(ref p, ref paths, ref b) => {
let mut mine = Vec::new();
for path in paths.iter() {
if !self.resolve_id(path.node.id, false, om, please_inline) {
if !self.resolve_id(path.node.id(), false, om, please_inline) {
mine.push(path.clone());
}
}
Expand Down
18 changes: 13 additions & 5 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1033,12 +1033,20 @@ pub struct Variant_ {
pub type Variant = Spanned<Variant_>;

#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub struct PathListIdent_ {
pub name: Ident,
pub id: NodeId,
pub enum PathListItem_ {
PathListIdent { pub name: Ident, pub id: NodeId },
PathListMod { pub id: NodeId }
}

impl PathListItem_ {
pub fn id(&self) -> NodeId {
match *self {
PathListIdent { id, .. } | PathListMod { id } => id
}
}
}

pub type PathListIdent = Spanned<PathListIdent_>;
pub type PathListItem = Spanned<PathListItem_>;

pub type ViewPath = Spanned<ViewPath_>;

Expand All @@ -1056,7 +1064,7 @@ pub enum ViewPath_ {
ViewPathGlob(Path, NodeId),

/// `foo::bar::{a,b,c}`
ViewPathList(Path, Vec<PathListIdent> , NodeId)
ViewPathList(Path, Vec<PathListItem> , NodeId)
}

#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/ast_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ impl<'a, O: IdVisitingOperation> Visitor<()> for IdVisitor<'a, O> {
ViewPathList(_, ref paths, node_id) => {
self.operation.visit_id(node_id);
for path in paths.iter() {
self.operation.visit_id(path.node.id)
self.operation.visit_id(path.node.id())
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/ext/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1045,7 +1045,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
fn view_use_list(&self, sp: Span, vis: ast::Visibility,
path: Vec<ast::Ident> , imports: &[ast::Ident]) -> ast::ViewItem {
let imports = imports.iter().map(|id| {
respan(sp, ast::PathListIdent_ { name: *id, id: ast::DUMMY_NODE_ID })
respan(sp, ast::PathListIdent { name: *id, id: ast::DUMMY_NODE_ID })
}).collect();

self.view_use(sp, vis,
Expand Down
18 changes: 9 additions & 9 deletions src/libsyntax/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,17 @@ pub trait Folder {
let id = self.new_id(node_id);
ViewPathList(self.fold_path(path),
path_list_idents.iter().map(|path_list_ident| {
let id = self.new_id(path_list_ident.node
.id);
Spanned {
node: PathListIdent_ {
name: path_list_ident.node
.name
.clone(),
id: id,
node: match path_list_ident.node {
PathListIdent { id, name } =>
PathListIdent {
id: self.new_id(id),
name: name.clone()
},
PathListMod { id } =>
PathListMod { id: self.new_id(id) }
},
span: self.new_span(
path_list_ident.span)
span: self.new_span(path_list_ident.span)
}
}).collect(),
id)
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
html_root_url = "http://doc.rust-lang.org/master/")]

#![feature(macro_rules, globs, managed_boxes, default_type_params, phase)]
#![feature(quote, unsafe_destructor)]
#![feature(quote, struct_variant, unsafe_destructor)]
#![allow(deprecated)]

extern crate fmt_macros;
Expand Down
16 changes: 10 additions & 6 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,12 +537,16 @@ impl<'a> Parser<'a> {
}
}

pub fn parse_path_list_ident(&mut self) -> ast::PathListIdent {
pub fn parse_path_list_item(&mut self) -> ast::PathListItem {
let lo = self.span.lo;
let ident = self.parse_ident();
let node = if self.eat_keyword(keywords::Mod) {
ast::PathListMod { id: ast::DUMMY_NODE_ID }
} else {
let ident = self.parse_ident();
ast::PathListIdent { name: ident, id: ast::DUMMY_NODE_ID }
};
let hi = self.last_span.hi;
spanned(lo, hi, ast::PathListIdent_ { name: ident,
id: ast::DUMMY_NODE_ID })
spanned(lo, hi, node)
}

/// Consume token 'tok' if it exists. Returns true if the given
Expand Down Expand Up @@ -5176,7 +5180,7 @@ impl<'a> Parser<'a> {
let idents = self.parse_unspanned_seq(
&token::LBRACE, &token::RBRACE,
seq_sep_trailing_allowed(token::COMMA),
|p| p.parse_path_list_ident());
|p| p.parse_path_list_item());
let path = ast::Path {
span: mk_sp(lo, self.span.hi),
global: false,
Expand Down Expand Up @@ -5232,7 +5236,7 @@ impl<'a> Parser<'a> {
&token::LBRACE,
&token::RBRACE,
seq_sep_trailing_allowed(token::COMMA),
|p| p.parse_path_list_ident()
|p| p.parse_path_list_item()
);
let path = ast::Path {
span: mk_sp(lo, self.span.hi),
Expand Down
9 changes: 8 additions & 1 deletion src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2182,7 +2182,14 @@ impl<'a> State<'a> {
try!(word(&mut self.s, "::{"));
}
try!(self.commasep(Inconsistent, idents.as_slice(), |s, w| {
s.print_ident(w.node.name)
match w.node {
ast::PathListIdent { name, .. } => {
s.print_ident(name)
},
ast::PathListMod { .. } => {
word(&mut s.s, "mod")
}
}
}));
word(&mut self.s, "}")
}
Expand Down
7 changes: 6 additions & 1 deletion src/libsyntax/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,12 @@ pub fn walk_view_item<E: Clone, V: Visitor<E>>(visitor: &mut V, vi: &ViewItem, e
}
ViewPathList(ref path, ref list, _) => {
for id in list.iter() {
visitor.visit_ident(id.span, id.node.name, env.clone())
match id.node {
PathListIdent { name, .. } => {
visitor.visit_ident(id.span, name, env.clone());
}
PathListMod { .. } => ()
}
}
walk_path(visitor, path, env.clone());
}
Expand Down
Loading