1
Fork 0

rollup merge of #20179: eddyb/blind-items

Conflicts:
	src/librustc/diagnostics.rs
	src/librustdoc/clean/mod.rs
	src/librustdoc/html/format.rs
	src/libsyntax/parse/parser.rs
This commit is contained in:
Alex Crichton 2015-01-21 11:56:00 -08:00
commit df1cddf20a
60 changed files with 1098 additions and 1520 deletions

View file

@ -803,8 +803,9 @@ Crates contain [items](#items), each of which may have some number of
## Items ## Items
```{.ebnf .gram} ```{.ebnf .gram}
item : mod_item | fn_item | type_item | struct_item | enum_item item : extern_crate_decl | use_decl | mod_item | fn_item | type_item
| static_item | trait_item | impl_item | extern_block ; | struct_item | enum_item | static_item | trait_item | impl_item
| extern_block ;
``` ```
An _item_ is a component of a crate; some module items can be defined in crate An _item_ is a component of a crate; some module items can be defined in crate
@ -818,6 +819,8 @@ execution, and may reside in read-only memory.
There are several kinds of item: There are several kinds of item:
* [`extern crate` declarations](#extern-crate-declarations)
* [`use` declarations](#use-declarations)
* [modules](#modules) * [modules](#modules)
* [functions](#functions) * [functions](#functions)
* [type definitions](#type-definitions) * [type definitions](#type-definitions)
@ -854,13 +857,10 @@ no notion of type abstraction: there are no first-class "forall" types.
```{.ebnf .gram} ```{.ebnf .gram}
mod_item : "mod" ident ( ';' | '{' mod '}' ); mod_item : "mod" ident ( ';' | '{' mod '}' );
mod : [ view_item | item ] * ; mod : item * ;
``` ```
A module is a container for zero or more [view items](#view-items) and zero or A module is a container for zero or more [items](#items).
more [items](#items). The view items manage the visibility of the items defined
within the module, as well as the visibility of names from outside the module
when referenced from inside the module.
A _module item_ is a module, surrounded in braces, named, and prefixed with the A _module item_ is a module, surrounded in braces, named, and prefixed with the
keyword `mod`. A module item introduces a new, named module into the tree of keyword `mod`. A module item introduces a new, named module into the tree of
@ -918,19 +918,6 @@ mod thread {
} }
``` ```
#### View items
```{.ebnf .gram}
view_item : extern_crate_decl | use_decl ;
```
A view item manages the namespace of a module. View items do not define new
items, but rather, simply change other items' visibility. There are two
kinds of view items:
* [`extern crate` declarations](#extern-crate-declarations)
* [`use` declarations](#use-declarations)
##### Extern crate declarations ##### Extern crate declarations
```{.ebnf .gram} ```{.ebnf .gram}
@ -2887,13 +2874,12 @@ Point3d {y: 0, z: 10, .. base};
### Block expressions ### Block expressions
```{.ebnf .gram} ```{.ebnf .gram}
block_expr : '{' [ view_item ] * block_expr : '{' [ stmt ';' | item ] *
[ stmt ';' | item ] *
[ expr ] '}' ; [ expr ] '}' ;
``` ```
A _block expression_ is similar to a module in terms of the declarations that A _block expression_ is similar to a module in terms of the declarations that
are possible. Each block conceptually introduces a new namespace scope. View are possible. Each block conceptually introduces a new namespace scope. Use
items can bring new names into scopes and declared items are in scope for only items can bring new names into scopes and declared items are in scope for only
the block itself. the block itself.

View file

@ -77,6 +77,9 @@ register_diagnostics! {
E0138, E0138,
E0139, E0139,
E0152, E0152,
E0153,
E0154,
E0157,
E0158, E0158,
E0161, E0161,
E0162, E0162,

View file

@ -1202,17 +1202,17 @@ impl LintPass for UnusedImportBraces {
lint_array!(UNUSED_IMPORT_BRACES) lint_array!(UNUSED_IMPORT_BRACES)
} }
fn check_view_item(&mut self, cx: &Context, view_item: &ast::ViewItem) { fn check_item(&mut self, cx: &Context, item: &ast::Item) {
match view_item.node { match item.node {
ast::ViewItemUse(ref view_path) => { ast::ItemUse(ref view_path) => {
match view_path.node { match view_path.node {
ast::ViewPathList(_, ref items, _) => { ast::ViewPathList(_, ref items) => {
if items.len() == 1 { if items.len() == 1 {
match items[0].node { match items[0].node {
ast::PathListIdent {ref name, ..} => { ast::PathListIdent {ref name, ..} => {
let m = format!("braces around {} is unnecessary", let m = format!("braces around {} is unnecessary",
token::get_ident(*name).get()); token::get_ident(*name).get());
cx.span_lint(UNUSED_IMPORT_BRACES, view_item.span, cx.span_lint(UNUSED_IMPORT_BRACES, item.span,
&m[]); &m[]);
}, },
_ => () _ => ()
@ -1709,22 +1709,6 @@ impl LintPass for Stability {
} }
} }
fn check_view_item(&mut self, cx: &Context, item: &ast::ViewItem) {
// compiler-generated `extern crate` statements have a dummy span.
if item.span == DUMMY_SP { return }
let id = match item.node {
ast::ViewItemExternCrate(_, _, id) => id,
ast::ViewItemUse(..) => return,
};
let cnum = match cx.tcx.sess.cstore.find_extern_mod_stmt_cnum(id) {
Some(cnum) => cnum,
None => return,
};
let id = ast::DefId { krate: cnum, node: ast::CRATE_NODE_ID };
self.lint(cx, id, item.span);
}
fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
if self.is_internal(cx, e.span) { return; } if self.is_internal(cx, e.span) { return; }
@ -1776,6 +1760,17 @@ impl LintPass for Stability {
if self.is_internal(cx, item.span) { return } if self.is_internal(cx, item.span) { return }
match item.node { match item.node {
ast::ItemExternCrate(_) => {
// compiler-generated `extern crate` items have a dummy span.
if item.span == DUMMY_SP { return }
let cnum = match cx.tcx.sess.cstore.find_extern_mod_stmt_cnum(item.id) {
Some(cnum) => cnum,
None => return,
};
let id = ast::DefId { krate: cnum, node: ast::CRATE_NODE_ID };
self.lint(cx, id, item.span);
}
ast::ItemTrait(_, _, ref supertraits, _) => { ast::ItemTrait(_, _, ref supertraits, _) => {
for t in supertraits.iter() { for t in supertraits.iter() {
if let ast::TraitTyParamBound(ref t, _) = *t { if let ast::TraitTyParamBound(ref t, _) = *t {

View file

@ -580,14 +580,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
}) })
} }
fn visit_view_item(&mut self, i: &ast::ViewItem) {
self.with_lint_attrs(&i.attrs[], |cx| {
run_lints!(cx, check_view_item, i);
cx.visit_ids(|v| v.visit_view_item(i));
visit::walk_view_item(cx, i);
})
}
fn visit_pat(&mut self, p: &ast::Pat) { fn visit_pat(&mut self, p: &ast::Pat) {
run_lints!(self, check_pat, p); run_lints!(self, check_pat, p);
visit::walk_pat(self, p); visit::walk_pat(self, p);

View file

@ -128,7 +128,6 @@ pub trait LintPass {
fn check_crate(&mut self, _: &Context, _: &ast::Crate) { } fn check_crate(&mut self, _: &Context, _: &ast::Crate) { }
fn check_ident(&mut self, _: &Context, _: Span, _: ast::Ident) { } fn check_ident(&mut self, _: &Context, _: Span, _: ast::Ident) { }
fn check_mod(&mut self, _: &Context, _: &ast::Mod, _: Span, _: ast::NodeId) { } fn check_mod(&mut self, _: &Context, _: &ast::Mod, _: Span, _: ast::NodeId) { }
fn check_view_item(&mut self, _: &Context, _: &ast::ViewItem) { }
fn check_foreign_item(&mut self, _: &Context, _: &ast::ForeignItem) { } fn check_foreign_item(&mut self, _: &Context, _: &ast::ForeignItem) { }
fn check_item(&mut self, _: &Context, _: &ast::Item) { } fn check_item(&mut self, _: &Context, _: &ast::Item) { }
fn check_local(&mut self, _: &Context, _: &ast::Local) { } fn check_local(&mut self, _: &Context, _: &ast::Local) { }

View file

@ -40,10 +40,6 @@ pub struct CrateReader<'a> {
} }
impl<'a, 'v> visit::Visitor<'v> for CrateReader<'a> { impl<'a, 'v> visit::Visitor<'v> for CrateReader<'a> {
fn visit_view_item(&mut self, a: &ast::ViewItem) {
self.process_view_item(a);
visit::walk_view_item(self, a);
}
fn visit_item(&mut self, a: &ast::Item) { fn visit_item(&mut self, a: &ast::Item) {
self.process_item(a); self.process_item(a);
visit::walk_item(self, a); visit::walk_item(self, a);
@ -64,9 +60,8 @@ fn dump_crates(cstore: &CStore) {
}) })
} }
fn should_link(i: &ast::ViewItem) -> bool { fn should_link(i: &ast::Item) -> bool {
!attr::contains_name(&i.attrs[], "no_link") !attr::contains_name(&i.attrs[], "no_link")
} }
struct CrateInfo { struct CrateInfo {
@ -181,29 +176,10 @@ impl<'a> CrateReader<'a> {
} }
} }
fn process_view_item(&mut self, i: &ast::ViewItem) { fn extract_crate_info(&self, i: &ast::Item) -> Option<CrateInfo> {
if !should_link(i) {
return;
}
match self.extract_crate_info(i) {
Some(info) => {
let (cnum, _, _) = self.resolve_crate(&None,
&info.ident[],
&info.name[],
None,
i.span,
PathKind::Crate);
self.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
}
None => ()
}
}
fn extract_crate_info(&self, i: &ast::ViewItem) -> Option<CrateInfo> {
match i.node { match i.node {
ast::ViewItemExternCrate(ident, ref path_opt, id) => { ast::ItemExternCrate(ref path_opt) => {
let ident = token::get_ident(ident); let ident = token::get_ident(i.ident);
debug!("resolving extern crate stmt. ident: {} path_opt: {:?}", debug!("resolving extern crate stmt. ident: {} path_opt: {:?}",
ident, path_opt); ident, path_opt);
let name = match *path_opt { let name = match *path_opt {
@ -218,7 +194,7 @@ impl<'a> CrateReader<'a> {
Some(CrateInfo { Some(CrateInfo {
ident: ident.get().to_string(), ident: ident.get().to_string(),
name: name, name: name,
id: id, id: i.id,
should_link: should_link(i), should_link: should_link(i),
}) })
} }
@ -226,8 +202,26 @@ impl<'a> CrateReader<'a> {
} }
} }
fn process_item(&self, i: &ast::Item) { fn process_item(&mut self, i: &ast::Item) {
match i.node { match i.node {
ast::ItemExternCrate(_) => {
if !should_link(i) {
return;
}
match self.extract_crate_info(i) {
Some(info) => {
let (cnum, _, _) = self.resolve_crate(&None,
&info.ident[],
&info.name[],
None,
i.span,
PathKind::Crate);
self.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
}
None => ()
}
}
ast::ItemForeignMod(ref fm) => { ast::ItemForeignMod(ref fm) => {
if fm.abi == abi::Rust || fm.abi == abi::RustIntrinsic { if fm.abi == abi::Rust || fm.abi == abi::RustIntrinsic {
return; return;
@ -533,7 +527,7 @@ impl<'a> CrateReader<'a> {
#[derive(Copy)] #[derive(Copy)]
pub enum CrateOrString<'a> { pub enum CrateOrString<'a> {
Krate(&'a ast::ViewItem), Krate(&'a ast::Item),
Str(&'a str) Str(&'a str)
} }

View file

@ -1456,8 +1456,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
rbml_w.end_tag(); rbml_w.end_tag();
} }
} }
ast::ItemMac(..) => { ast::ItemExternCrate(_) | ast::ItemUse(_) |ast::ItemMac(..) => {
// macros are encoded separately // these are encoded separately
} }
} }
} }

View file

@ -332,8 +332,6 @@ impl Folder for NestedItemsDropper {
} }
}).collect(); }).collect();
let blk_sans_items = P(ast::Block { let blk_sans_items = P(ast::Block {
view_items: Vec::new(), // I don't know if we need the view_items
// here, but it doesn't break tests!
stmts: stmts_sans_items, stmts: stmts_sans_items,
expr: expr, expr: expr,
id: id, id: id,

View file

@ -297,6 +297,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
// These are normal, nothing reachable about these // These are normal, nothing reachable about these
// inherently and their children are already in the // inherently and their children are already in the
// worklist, as determined by the privacy pass // worklist, as determined by the privacy pass
ast::ItemExternCrate(_) | ast::ItemUse(_) |
ast::ItemTy(..) | ast::ItemStatic(_, _, _) | ast::ItemTy(..) | ast::ItemStatic(_, _, _) |
ast::ItemMod(..) | ast::ItemForeignMod(..) | ast::ItemMod(..) | ast::ItemForeignMod(..) |
ast::ItemImpl(..) | ast::ItemTrait(..) | ast::ItemImpl(..) | ast::ItemTrait(..) |

View file

@ -94,6 +94,8 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
// Fn lifetimes get added in visit_fn below: // Fn lifetimes get added in visit_fn below:
visit::walk_item(this, item); visit::walk_item(this, item);
} }
ast::ItemExternCrate(_) |
ast::ItemUse(_) |
ast::ItemMod(..) | ast::ItemMod(..) |
ast::ItemMac(..) | ast::ItemMac(..) |
ast::ItemForeignMod(..) | ast::ItemForeignMod(..) |

View file

@ -73,8 +73,10 @@ pub fn load_plugins(sess: &Session, krate: &ast::Crate,
// We need to error on `#[macro_use] extern crate` when it isn't at the // We need to error on `#[macro_use] extern crate` when it isn't at the
// crate root, because `$crate` won't work properly. Identify these by // crate root, because `$crate` won't work properly. Identify these by
// spans, because the crate map isn't set up yet. // spans, because the crate map isn't set up yet.
for vi in krate.module.view_items.iter() { for item in krate.module.items.iter() {
loader.span_whitelist.insert(vi.span); if let ast::ItemExternCrate(_) = item.node {
loader.span_whitelist.insert(item.span);
}
} }
visit::walk_crate(&mut loader, krate); visit::walk_crate(&mut loader, krate);
@ -91,18 +93,21 @@ pub fn load_plugins(sess: &Session, krate: &ast::Crate,
// note that macros aren't expanded yet, and therefore macros can't add plugins. // note that macros aren't expanded yet, and therefore macros can't add plugins.
impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
fn visit_view_item(&mut self, vi: &ast::ViewItem) { fn visit_item(&mut self, item: &ast::Item) {
// We're only interested in `extern crate`. // We're only interested in `extern crate`.
match vi.node { match item.node {
ast::ViewItemExternCrate(..) => (), ast::ItemExternCrate(_) => {}
_ => return, _ => {
visit::walk_item(self, item);
return;
}
} }
// Parse the attributes relating to macro / plugin loading. // Parse the attributes relating to macro / plugin loading.
let mut plugin_attr = None; let mut plugin_attr = None;
let mut macro_selection = Some(HashSet::new()); // None => load all let mut macro_selection = Some(HashSet::new()); // None => load all
let mut reexport = HashSet::new(); let mut reexport = HashSet::new();
for attr in vi.attrs.iter() { for attr in item.attrs.iter() {
let mut used = true; let mut used = true;
match attr.name().get() { match attr.name().get() {
"phase" => { "phase" => {
@ -155,7 +160,10 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
} }
} }
self.load_plugin(CrateOrString::Krate(vi), plugin_attr, macro_selection, Some(reexport)) self.load_plugin(CrateOrString::Krate(item),
plugin_attr,
macro_selection,
Some(reexport))
} }
fn visit_mac(&mut self, _: &ast::Mac) { fn visit_mac(&mut self, _: &ast::Mac) {

View file

@ -182,7 +182,6 @@ mod svh_visitor {
SawLifetimeDef(token::InternedString), SawLifetimeDef(token::InternedString),
SawMod, SawMod,
SawViewItem,
SawForeignItem, SawForeignItem,
SawItem, SawItem,
SawDecl, SawDecl,
@ -430,19 +429,6 @@ mod svh_visitor {
SawStmt(saw_stmt(&s.node)).hash(self.st); visit::walk_stmt(self, s) SawStmt(saw_stmt(&s.node)).hash(self.st); visit::walk_stmt(self, s)
} }
fn visit_view_item(&mut self, i: &ViewItem) {
// Two kinds of view items can affect the ABI for a crate:
// exported `pub use` view items (since that may expose
// items that downstream crates can call), and `use
// foo::Trait`, since changing that may affect method
// resolution.
//
// The simplest approach to handling both of the above is
// just to adopt the same simple-minded (fine-grained)
// hash that I am deploying elsewhere here.
SawViewItem.hash(self.st); visit::walk_view_item(self, i)
}
fn visit_foreign_item(&mut self, i: &ForeignItem) { fn visit_foreign_item(&mut self, i: &ForeignItem) {
// FIXME (#14132) ideally we would incorporate privacy (or // FIXME (#14132) ideally we would incorporate privacy (or
// perhaps reachability) somewhere here, so foreign items // perhaps reachability) somewhere here, so foreign items

View file

@ -477,7 +477,7 @@ impl fold::Folder for ReplaceBodyWithLoop {
e: Option<P<ast::Expr>>) -> P<ast::Block> { e: Option<P<ast::Expr>>) -> P<ast::Block> {
P(ast::Block { P(ast::Block {
expr: e, expr: e,
view_items: vec![], stmts: vec![], rules: rules, stmts: vec![], rules: rules,
id: ast::DUMMY_NODE_ID, span: codemap::DUMMY_SP, id: ast::DUMMY_NODE_ID, span: codemap::DUMMY_SP,
}) })
} }

View file

@ -200,6 +200,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
} }
return match it.node { return match it.node {
ast::ItemUse(..) | ast::ItemExternCrate(..) |
ast::ItemConst(..) | ast::ItemStatic(..) | ast::ItemFn(..) | ast::ItemConst(..) | ast::ItemStatic(..) | ast::ItemFn(..) |
ast::ItemForeignMod(..) | ast::ItemTy(..) => { ast::ItemForeignMod(..) | ast::ItemTy(..) => {
None None

View file

@ -830,6 +830,38 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &ast::Item) { fn visit_item(&mut self, item: &ast::Item) {
match item.node {
ast::ItemUse(ref vpath) => {
match vpath.node {
ast::ViewPathSimple(..) | ast::ViewPathGlob(..) => {}
ast::ViewPathList(ref prefix, ref list) => {
for pid in list.iter() {
match pid.node {
ast::PathListIdent { id, name } => {
debug!("privacy - ident item {}", id);
let seg = ast::PathSegment {
identifier: name,
parameters: ast::PathParameters::none(),
};
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);
}
}
}
}
}
}
_ => {}
}
let orig_curitem = replace(&mut self.curitem, item.id); let orig_curitem = replace(&mut self.curitem, item.id);
visit::walk_item(self, item); visit::walk_item(self, item);
self.curitem = orig_curitem; self.curitem = orig_curitem;
@ -926,42 +958,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
visit::walk_expr(self, expr); visit::walk_expr(self, expr);
} }
fn visit_view_item(&mut self, a: &ast::ViewItem) {
match a.node {
ast::ViewItemExternCrate(..) => {}
ast::ViewItemUse(ref vpath) => {
match vpath.node {
ast::ViewPathSimple(..) | ast::ViewPathGlob(..) => {}
ast::ViewPathList(ref prefix, ref list, _) => {
for pid in list.iter() {
match pid.node {
ast::PathListIdent { id, name } => {
debug!("privacy - ident item {}", id);
let seg = ast::PathSegment {
identifier: name,
parameters: ast::PathParameters::none(),
};
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);
}
}
}
}
}
}
}
visit::walk_view_item(self, a);
}
fn visit_pat(&mut self, pattern: &ast::Pat) { fn visit_pat(&mut self, pattern: &ast::Pat) {
// Foreign functions do not have their patterns mapped in the def_map, // Foreign functions do not have their patterns mapped in the def_map,
// and there's nothing really relevant there anyway, so don't bother // and there's nothing really relevant there anyway, so don't bother
@ -1069,23 +1065,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for SanePrivacyVisitor<'a, 'tcx> {
visit::walk_fn(self, fk, fd, b, s); visit::walk_fn(self, fk, fd, b, s);
self.in_fn = orig_in_fn; self.in_fn = orig_in_fn;
} }
fn visit_view_item(&mut self, i: &ast::ViewItem) {
match i.vis {
ast::Inherited => {}
ast::Public => {
if self.in_fn {
self.tcx.sess.span_err(i.span, "unnecessary `pub`, imports \
in functions are never \
reachable");
} else if let ast::ViewItemExternCrate(..) = i.node {
self.tcx.sess.span_err(i.span, "`pub` visibility \
is not allowed");
}
}
}
visit::walk_view_item(self, i);
}
} }
impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
@ -1162,7 +1141,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
ast::ItemConst(..) | ast::ItemStatic(..) | ast::ItemStruct(..) | ast::ItemConst(..) | ast::ItemStatic(..) | ast::ItemStruct(..) |
ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) | ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) |
ast::ItemMac(..) => {} ast::ItemExternCrate(_) | ast::ItemUse(_) | ast::ItemMac(..) => {}
} }
} }
@ -1219,6 +1198,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
} }
} }
ast::ItemExternCrate(_) | ast::ItemUse(_) |
ast::ItemStatic(..) | ast::ItemConst(..) | ast::ItemStatic(..) | ast::ItemConst(..) |
ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) | ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) |
ast::ItemMac(..) => {} ast::ItemMac(..) => {}
@ -1521,11 +1501,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
// we don't need to introspect into these at all: an // we don't need to introspect into these at all: an
// expression/block context can't possibly contain exported // expression/block context can't possibly contain exported things.
// things, and neither do view_items. (Making them no-ops stops us // (Making them no-ops stops us from traversing the whole AST without
// from traversing the whole AST without having to be super // having to be super careful about our `walk_...` calls above.)
// careful about our `walk_...` calls above.)
fn visit_view_item(&mut self, _: &ast::ViewItem) {}
fn visit_block(&mut self, _: &ast::Block) {} fn visit_block(&mut self, _: &ast::Block) {}
fn visit_expr(&mut self, _: &ast::Expr) {} fn visit_expr(&mut self, _: &ast::Expr) {}
} }

View file

@ -39,9 +39,9 @@ use rustc::middle::subst::FnSpace;
use syntax::ast::{Block, Crate}; use syntax::ast::{Block, Crate};
use syntax::ast::{DeclItem, DefId}; use syntax::ast::{DeclItem, DefId};
use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic}; use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic};
use syntax::ast::{Item, ItemConst, ItemEnum, ItemFn}; use syntax::ast::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};
use syntax::ast::{ItemStruct, ItemTrait, ItemTy}; use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse};
use syntax::ast::{MethodImplItem, Name, NamedField, NodeId}; use syntax::ast::{MethodImplItem, Name, NamedField, NodeId};
use syntax::ast::{PathListIdent, PathListMod}; use syntax::ast::{PathListIdent, PathListMod};
use syntax::ast::{Public, SelfStatic}; use syntax::ast::{Public, SelfStatic};
@ -50,8 +50,7 @@ use syntax::ast::StructVariantKind;
use syntax::ast::TupleVariantKind; use syntax::ast::TupleVariantKind;
use syntax::ast::TyObjectSum; use syntax::ast::TyObjectSum;
use syntax::ast::{TypeImplItem, UnnamedField}; use syntax::ast::{TypeImplItem, UnnamedField};
use syntax::ast::{Variant, ViewItem, ViewItemExternCrate}; use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
use syntax::ast::{ViewItemUse, ViewPathGlob, ViewPathList, ViewPathSimple};
use syntax::ast::{Visibility}; use syntax::ast::{Visibility};
use syntax::ast::TyPath; use syntax::ast::TyPath;
use syntax::ast; use syntax::ast;
@ -238,11 +237,6 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
} }
fn block_needs_anonymous_module(&mut self, block: &Block) -> bool { fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
// If the block has view items, we need an anonymous module.
if block.view_items.len() > 0 {
return true;
}
// Check each statement. // Check each statement.
for statement in block.stmts.iter() { for statement in block.stmts.iter() {
match statement.node { match statement.node {
@ -262,7 +256,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
} }
} }
// If we found neither view items nor items, we don't need to create // If we found no items, we don't need to create
// an anonymous module. // an anonymous module.
return false; return false;
@ -280,6 +274,133 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
match item.node { match item.node {
ItemUse(ref view_path) => {
// 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 module_path = match view_path.node {
ViewPathSimple(_, ref full_path) => {
full_path.segments
.init()
.iter().map(|ident| ident.identifier.name)
.collect()
}
ViewPathGlob(ref module_ident_path) |
ViewPathList(ref module_ident_path, _) => {
module_ident_path.segments
.iter().map(|ident| ident.identifier.name).collect()
}
};
// Build up the import directives.
let shadowable = item.attrs.iter().any(|attr| {
attr.name() == token::get_name(special_idents::prelude_import.name)
});
let shadowable = if shadowable {
Shadowable::Always
} else {
Shadowable::Never
};
match view_path.node {
ViewPathSimple(binding, ref full_path) => {
let source_name =
full_path.segments.last().unwrap().identifier.name;
if token::get_name(source_name).get() == "mod" ||
token::get_name(source_name).get() == "self" {
self.resolve_error(view_path.span,
"`self` imports are only allowed within a { } list");
}
let subclass = SingleImport(binding.name,
source_name);
self.build_import_directive(&**parent,
module_path,
subclass,
view_path.span,
item.id,
is_public,
shadowable);
}
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>>();
if mod_spans.len() > 1 {
self.resolve_error(mod_spans[0],
"`self` import can only appear once in the list");
for other_span in mod_spans.iter().skip(1) {
self.session.span_note(*other_span,
"another `self` import appears here");
}
}
for source_item in source_items.iter() {
let (module_path, name) = match source_item.node {
PathListIdent { name, .. } =>
(module_path.clone(), name.name),
PathListMod { .. } => {
let name = match module_path.last() {
Some(name) => *name,
None => {
self.resolve_error(source_item.span,
"`self` import can only appear in an import list \
with a non-empty prefix");
continue;
}
};
let module_path = module_path.init();
(module_path.to_vec(), name)
}
};
self.build_import_directive(
&**parent,
module_path,
SingleImport(name, name),
source_item.span,
source_item.node.id(),
is_public,
shadowable);
}
}
ViewPathGlob(_) => {
self.build_import_directive(&**parent,
module_path,
GlobImport,
view_path.span,
item.id,
is_public,
shadowable);
}
}
parent.clone()
}
ItemExternCrate(_) => {
// n.b. we don't need to look at the path option here, because cstore already did
for &crate_id in self.session.cstore
.find_extern_mod_stmt_cnum(item.id).iter() {
let def_id = DefId { krate: crate_id, node: 0 };
self.external_exports.insert(def_id);
let parent_link = ModuleParentLink(parent.downgrade(), name);
let external_module = Rc::new(Module::new(parent_link,
Some(def_id),
NormalModuleKind,
false,
true));
debug!("(build reduced graph for item) found extern `{}`",
self.module_to_string(&*external_module));
self.check_for_conflicts_between_external_crates(&**parent, name, sp);
parent.external_module_children.borrow_mut()
.insert(name, external_module.clone());
self.build_reduced_graph_for_external_crate(&external_module);
}
parent.clone()
}
ItemMod(..) => { ItemMod(..) => {
let name_bindings = self.add_child(name, parent, ForbidDuplicateModules, sp); let name_bindings = self.add_child(name, parent, ForbidDuplicateModules, sp);
@ -650,145 +771,6 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
variant.span, PUBLIC | IMPORTABLE); variant.span, PUBLIC | IMPORTABLE);
} }
/// Constructs the reduced graph for one 'view item'. View items consist
/// of imports and use directives.
fn build_reduced_graph_for_view_item(&mut self, view_item: &ViewItem, parent: &Rc<Module>) {
match view_item.node {
ViewItemUse(ref view_path) => {
// 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 module_path = match view_path.node {
ViewPathSimple(_, ref full_path, _) => {
full_path.segments
.init()
.iter().map(|ident| ident.identifier.name)
.collect()
}
ViewPathGlob(ref module_ident_path, _) |
ViewPathList(ref module_ident_path, _, _) => {
module_ident_path.segments
.iter().map(|ident| ident.identifier.name).collect()
}
};
// Build up the import directives.
let is_public = view_item.vis == ast::Public;
let shadowable =
view_item.attrs
.iter()
.any(|attr| {
attr.name() == token::get_name(
special_idents::prelude_import.name)
});
let shadowable = if shadowable {
Shadowable::Always
} else {
Shadowable::Never
};
match view_path.node {
ViewPathSimple(binding, ref full_path, id) => {
let source_name =
full_path.segments.last().unwrap().identifier.name;
if token::get_name(source_name).get() == "mod" ||
token::get_name(source_name).get() == "self" {
self.resolve_error(view_path.span,
"`self` imports are only allowed within a { } list");
}
let subclass = SingleImport(binding.name,
source_name);
self.build_import_directive(&**parent,
module_path,
subclass,
view_path.span,
id,
is_public,
shadowable);
}
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>>();
if mod_spans.len() > 1 {
self.resolve_error(mod_spans[0],
"`self` import can only appear once in the list");
for other_span in mod_spans.iter().skip(1) {
self.session.span_note(*other_span,
"another `self` import appears here");
}
}
for source_item in source_items.iter() {
let (module_path, name) = match source_item.node {
PathListIdent { name, .. } =>
(module_path.clone(), name.name),
PathListMod { .. } => {
let name = match module_path.last() {
Some(name) => *name,
None => {
self.resolve_error(source_item.span,
"`self` import can only appear in an import list \
with a non-empty prefix");
continue;
}
};
let module_path = module_path.init();
(module_path.to_vec(), name)
}
};
self.build_import_directive(
&**parent,
module_path,
SingleImport(name, name),
source_item.span,
source_item.node.id(),
is_public,
shadowable);
}
}
ViewPathGlob(_, id) => {
self.build_import_directive(&**parent,
module_path,
GlobImport,
view_path.span,
id,
is_public,
shadowable);
}
}
}
ViewItemExternCrate(name, _, node_id) => {
// n.b. we don't need to look at the path option here, because cstore already did
for &crate_id in self.session.cstore
.find_extern_mod_stmt_cnum(node_id).iter() {
let def_id = DefId { krate: crate_id, node: 0 };
self.external_exports.insert(def_id);
let parent_link = ModuleParentLink(parent.downgrade(), name.name);
let external_module = Rc::new(Module::new(parent_link,
Some(def_id),
NormalModuleKind,
false,
true));
debug!("(build reduced graph for item) found extern `{}`",
self.module_to_string(&*external_module));
self.check_for_conflicts_between_external_crates(
&**parent,
name.name,
view_item.span);
parent.external_module_children.borrow_mut()
.insert(name.name, external_module.clone());
self.build_reduced_graph_for_external_crate(&external_module);
}
}
}
}
/// Constructs the reduced graph for one foreign item. /// Constructs the reduced graph for one foreign item.
fn build_reduced_graph_for_foreign_item<F>(&mut self, fn build_reduced_graph_for_foreign_item<F>(&mut self,
foreign_item: &ForeignItem, foreign_item: &ForeignItem,
@ -1270,10 +1252,6 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
}) })
} }
fn visit_view_item(&mut self, view_item: &ViewItem) {
self.builder.build_reduced_graph_for_view_item(view_item, &self.parent);
}
fn visit_block(&mut self, block: &Block) { fn visit_block(&mut self, block: &Block) {
let np = self.builder.build_reduced_graph_for_block(block, &self.parent); let np = self.builder.build_reduced_graph_for_block(block, &self.parent);
let old_parent = replace(&mut self.parent, np); let old_parent = replace(&mut self.parent, np);

View file

@ -25,7 +25,6 @@ use Namespace::{TypeNS, ValueNS};
use rustc::lint; use rustc::lint;
use rustc::middle::privacy::{DependsOn, LastImport, Used, Unused}; use rustc::middle::privacy::{DependsOn, LastImport, Used, Unused};
use syntax::ast; use syntax::ast;
use syntax::ast::{ViewItem, ViewItemExternCrate, ViewItemUse};
use syntax::ast::{ViewPathGlob, ViewPathList, ViewPathSimple}; use syntax::ast::{ViewPathGlob, ViewPathList, ViewPathSimple};
use syntax::codemap::{Span, DUMMY_SP}; use syntax::codemap::{Span, DUMMY_SP};
use syntax::visit::{self, Visitor}; use syntax::visit::{self, Visitor};
@ -109,53 +108,54 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
} }
impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
fn visit_view_item(&mut self, vi: &ViewItem) { fn visit_item(&mut self, item: &ast::Item) {
// Ignore is_public import statements because there's no way to be sure // Ignore is_public import statements because there's no way to be sure
// whether they're used or not. Also ignore imports with a dummy span // whether they're used or not. Also ignore imports with a dummy span
// because this means that they were generated in some fashion by the // because this means that they were generated in some fashion by the
// compiler and we don't need to consider them. // compiler and we don't need to consider them.
if vi.vis == ast::Public || vi.span == DUMMY_SP { if item.vis == ast::Public || item.span == DUMMY_SP {
visit::walk_view_item(self, vi); visit::walk_item(self, item);
return; return;
} }
match vi.node { match item.node {
ViewItemExternCrate(_, _, id) => { ast::ItemExternCrate(_) => {
if let Some(crate_num) = self.session.cstore.find_extern_mod_stmt_cnum(id) { if let Some(crate_num) = self.session.cstore.find_extern_mod_stmt_cnum(item.id) {
if !self.used_crates.contains(&crate_num) { if !self.used_crates.contains(&crate_num) {
self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATES, self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATES,
id, item.id,
vi.span, item.span,
"unused extern crate".to_string()); "unused extern crate".to_string());
} }
} }
}, },
ViewItemUse(ref p) => { ast::ItemUse(ref p) => {
match p.node { match p.node {
ViewPathSimple(_, _, id) => { ViewPathSimple(_, _) => {
self.finalize_import(id, p.span) self.finalize_import(item.id, p.span)
} }
ViewPathList(_, ref list, _) => { ViewPathList(_, ref list) => {
for i in list.iter() { for i in list.iter() {
self.finalize_import(i.node.id(), i.span); self.finalize_import(i.node.id(), i.span);
} }
} }
ViewPathGlob(_, id) => { ViewPathGlob(_) => {
if !self.used_imports.contains(&(id, TypeNS)) && if !self.used_imports.contains(&(item.id, TypeNS)) &&
!self.used_imports.contains(&(id, ValueNS)) { !self.used_imports.contains(&(item.id, ValueNS)) {
self.session self.session
.add_lint(lint::builtin::UNUSED_IMPORTS, .add_lint(lint::builtin::UNUSED_IMPORTS,
id, item.id,
p.span, p.span,
"unused import".to_string()); "unused import".to_string());
} }
} }
} }
} }
_ => {}
} }
visit::walk_view_item(self, vi); visit::walk_item(self, item);
} }
} }

View file

@ -65,10 +65,10 @@ use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField};
use syntax::ast::{ExprClosure, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall}; use syntax::ast::{ExprClosure, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall};
use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl}; use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl};
use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics}; use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics};
use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemFn}; use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate};
use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};
use syntax::ast::{ItemStruct, ItemTrait, ItemTy, Local, LOCAL_CRATE}; use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse};
use syntax::ast::{MethodImplItem, Mod, Name, NodeId}; use syntax::ast::{Local, MethodImplItem, Mod, Name, NodeId};
use syntax::ast::{Pat, PatEnum, PatIdent, PatLit}; use syntax::ast::{Pat, PatEnum, PatIdent, PatLit};
use syntax::ast::{PatRange, PatStruct, Path}; use syntax::ast::{PatRange, PatStruct, Path};
use syntax::ast::{PolyTraitRef, PrimTy, SelfExplicit}; use syntax::ast::{PolyTraitRef, PrimTy, SelfExplicit};
@ -1143,7 +1143,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} }
fn get_trait_name(&self, did: DefId) -> Name { fn get_trait_name(&self, did: DefId) -> Name {
if did.krate == LOCAL_CRATE { if did.krate == ast::LOCAL_CRATE {
self.ast_map.expect_item(did.node).ident.name self.ast_map.expect_item(did.node).ident.name
} else { } else {
csearch::get_trait_name(&self.session.cstore, did) csearch::get_trait_name(&self.session.cstore, did)
@ -1752,10 +1752,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
import_span: Span, import_span: Span,
name: Name, name: Name,
namespace: Namespace) { namespace: Namespace) {
if self.session.features.borrow().import_shadowing {
return
}
debug!("check_for_conflicting_import: {}; target exists: {}", debug!("check_for_conflicting_import: {}; target exists: {}",
token::get_name(name).get(), token::get_name(name).get(),
target.is_some()); target.is_some());
@ -1795,10 +1791,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&ImportResolution, &ImportResolution,
import_span: Span, import_span: Span,
name: Name) { name: Name) {
if self.session.features.borrow().import_shadowing {
return
}
// First, check for conflicts between imports and `extern crate`s. // First, check for conflicts between imports and `extern crate`s.
if module.external_module_children if module.external_module_children
.borrow() .borrow()
@ -1892,10 +1884,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
module: &Module, module: &Module,
name: Name, name: Name,
span: Span) { span: Span) {
if self.session.features.borrow().import_shadowing {
return
}
if module.external_module_children.borrow().contains_key(&name) { if module.external_module_children.borrow().contains_key(&name) {
span_err!(self.session, span, E0259, span_err!(self.session, span, E0259,
"an external crate named `{}` has already \ "an external crate named `{}` has already \
@ -1909,10 +1897,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
module: &Module, module: &Module,
name: Name, name: Name,
span: Span) { span: Span) {
if self.session.features.borrow().import_shadowing {
return
}
if module.external_module_children.borrow().contains_key(&name) { if module.external_module_children.borrow().contains_key(&name) {
span_err!(self.session, span, E0260, span_err!(self.session, span, E0260,
"the name `{}` conflicts with an external \ "the name `{}` conflicts with an external \
@ -2984,9 +2968,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}); });
} }
ItemMac(..) => { ItemExternCrate(_) | ItemUse(_) | ItemMac(..) => {
// do nothing, these are just around to be encoded // do nothing, these are just around to be encoded
} }
} }
} }
@ -3527,6 +3511,26 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} }
} }
// Check for imports appearing after non-item statements.
let mut found_non_item = false;
for statement in block.stmts.iter() {
if let ast::StmtDecl(ref declaration, _) = statement.node {
if let ast::DeclItem(ref i) = declaration.node {
match i.node {
ItemExternCrate(_) | ItemUse(_) if found_non_item => {
span_err!(self.session, i.span, E0154,
"imports are not allowed after non-item statements");
}
_ => {}
}
} else {
found_non_item = true
}
} else {
found_non_item = true;
}
}
// Descend into the block. // Descend into the block.
visit::walk_block(self, block); visit::walk_block(self, block);

View file

@ -1037,6 +1037,110 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
} }
match item.node { match item.node {
ast::ItemUse(ref use_item) => {
match use_item.node {
ast::ViewPathSimple(ident, ref path) => {
let sub_span = self.span.span_for_last_ident(path.span);
let mod_id = match self.lookup_type_ref(item.id) {
Some(def_id) => {
match self.lookup_def_kind(item.id, path.span) {
Some(kind) => self.fmt.ref_str(kind,
path.span,
sub_span,
def_id,
self.cur_scope),
None => {},
}
Some(def_id)
},
None => None,
};
// 'use' always introduces an alias, if there is not an explicit
// one, there is an implicit one.
let sub_span =
match self.span.sub_span_after_keyword(use_item.span, keywords::As) {
Some(sub_span) => Some(sub_span),
None => sub_span,
};
self.fmt.use_alias_str(path.span,
sub_span,
item.id,
mod_id,
get_ident(ident).get(),
self.cur_scope);
self.write_sub_paths_truncated(path);
}
ast::ViewPathGlob(ref path) => {
// Make a comma-separated list of names of imported modules.
let mut name_string = String::new();
let glob_map = &self.analysis.glob_map;
let glob_map = glob_map.as_ref().unwrap();
if glob_map.contains_key(&item.id) {
for n in glob_map[item.id].iter() {
if name_string.len() > 0 {
name_string.push_str(", ");
}
name_string.push_str(n.as_str());
}
}
let sub_span = self.span.sub_span_of_token(path.span,
token::BinOp(token::Star));
self.fmt.use_glob_str(path.span,
sub_span,
item.id,
name_string.as_slice(),
self.cur_scope);
self.write_sub_paths(path);
}
ast::ViewPathList(ref path, ref list) => {
for plid in list.iter() {
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, self.cur_scope);
}
None => ()
},
None => ()
}
},
ast::PathListMod { .. } => ()
}
}
self.write_sub_paths(path);
}
}
}
ast::ItemExternCrate(ref s) => {
let name = get_ident(item.ident);
let name = name.get();
let s = match *s {
Some((ref s, _)) => s.get().to_string(),
None => name.to_string(),
};
let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Crate);
let cnum = match self.sess.cstore.find_extern_mod_stmt_cnum(item.id) {
Some(cnum) => cnum,
None => 0,
};
self.fmt.extern_crate_str(item.span,
sub_span,
item.id,
cnum,
name,
&s[],
self.cur_scope);
}
ast::ItemFn(ref decl, _, _, ref ty_params, ref body) => ast::ItemFn(ref decl, _, _, ref ty_params, ref body) =>
self.process_fn(item, &**decl, ty_params, &**body), self.process_fn(item, &**decl, ty_params, &**body),
ast::ItemStatic(ref typ, mt, ref expr) => ast::ItemStatic(ref typ, mt, ref expr) =>
@ -1160,119 +1264,6 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
} }
} }
fn visit_view_item(&mut self, i: &ast::ViewItem) {
if generated_code(i.span) {
return
}
match i.node {
ast::ViewItemUse(ref item) => {
match item.node {
ast::ViewPathSimple(ident, ref path, id) => {
let sub_span = self.span.span_for_last_ident(path.span);
let mod_id = match self.lookup_type_ref(id) {
Some(def_id) => {
match self.lookup_def_kind(id, path.span) {
Some(kind) => self.fmt.ref_str(kind,
path.span,
sub_span,
def_id,
self.cur_scope),
None => {},
}
Some(def_id)
},
None => None,
};
// 'use' always introduces an alias, if there is not an explicit
// one, there is an implicit one.
let sub_span =
match self.span.sub_span_after_keyword(item.span, keywords::As) {
Some(sub_span) => Some(sub_span),
None => sub_span,
};
self.fmt.use_alias_str(path.span,
sub_span,
id,
mod_id,
get_ident(ident).get(),
self.cur_scope);
self.write_sub_paths_truncated(path);
}
ast::ViewPathGlob(ref path, id) => {
// Make a comma-separated list of names of imported modules.
let mut name_string = String::new();
let glob_map = &self.analysis.glob_map;
let glob_map = glob_map.as_ref().unwrap();
if glob_map.contains_key(&id) {
for n in glob_map[id].iter() {
if name_string.len() > 0 {
name_string.push_str(", ");
}
name_string.push_str(n.as_str());
}
}
let sub_span = self.span.sub_span_of_token(path.span,
token::BinOp(token::Star));
self.fmt.use_glob_str(path.span,
sub_span,
id,
name_string.as_slice(),
self.cur_scope);
self.write_sub_paths(path);
}
ast::ViewPathList(ref path, ref list, _) => {
for plid in list.iter() {
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, self.cur_scope);
}
None => ()
},
None => ()
}
},
ast::PathListMod { .. } => ()
}
}
self.write_sub_paths(path);
}
}
},
ast::ViewItemExternCrate(ident, ref s, id) => {
let name = get_ident(ident);
let name = name.get();
let s = match *s {
Some((ref s, _)) => s.get().to_string(),
None => name.to_string(),
};
let sub_span = self.span.sub_span_after_keyword(i.span, keywords::Crate);
let cnum = match self.sess.cstore.find_extern_mod_stmt_cnum(id) {
Some(cnum) => cnum,
None => 0,
};
self.fmt.extern_crate_str(i.span,
sub_span,
id,
cnum,
name,
&s[],
self.cur_scope);
},
}
}
fn visit_ty(&mut self, t: &ast::Ty) { fn visit_ty(&mut self, t: &ast::Ty) {
if generated_code(t.span) { if generated_code(t.span) {
return return

View file

@ -274,7 +274,6 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
ast_map::NodeArg(..) | ast_map::NodeArg(..) |
ast_map::NodeBlock(..) | ast_map::NodeBlock(..) |
ast_map::NodePat(..) | ast_map::NodePat(..) |
ast_map::NodeViewItem(..) |
ast_map::NodeLocal(..) => { ast_map::NodeLocal(..) => {
ccx.sess().bug(&format!("can't monomorphize a {:?}", ccx.sess().bug(&format!("can't monomorphize a {:?}",
map_node)[]) map_node)[])

View file

@ -555,6 +555,7 @@ fn convert(ccx: &CollectCtxt, it: &ast::Item) {
debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id); debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
match it.node { match it.node {
// These don't define types. // These don't define types.
ast::ItemExternCrate(_) | ast::ItemUse(_) |
ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {} ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
ast::ItemEnum(ref enum_definition, ref generics) => { ast::ItemEnum(ref enum_definition, ref generics) => {
let scheme = ty_of_item(ccx, it); let scheme = ty_of_item(ccx, it);
@ -1004,6 +1005,7 @@ fn ty_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Item)
tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone()); tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
return scheme; return scheme;
} }
ast::ItemExternCrate(_) | ast::ItemUse(_) |
ast::ItemImpl(..) | ast::ItemMod(_) | ast::ItemImpl(..) | ast::ItemMod(_) |
ast::ItemForeignMod(_) | ast::ItemMac(_) => panic!(), ast::ItemForeignMod(_) | ast::ItemMac(_) => panic!(),
} }

View file

@ -380,6 +380,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> {
visit::walk_item(self, item); visit::walk_item(self, item);
} }
ast::ItemExternCrate(_) |
ast::ItemUse(_) |
ast::ItemImpl(..) | ast::ItemImpl(..) |
ast::ItemStatic(..) | ast::ItemStatic(..) |
ast::ItemConst(..) | ast::ItemConst(..) |
@ -532,6 +534,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
} }
} }
ast::ItemExternCrate(_) |
ast::ItemUse(_) |
ast::ItemStatic(..) | ast::ItemStatic(..) |
ast::ItemConst(..) | ast::ItemConst(..) |
ast::ItemFn(..) | ast::ItemFn(..) |

View file

@ -18,8 +18,7 @@ pub use self::TypeKind::*;
pub use self::StructField::*; pub use self::StructField::*;
pub use self::VariantKind::*; pub use self::VariantKind::*;
pub use self::Mutability::*; pub use self::Mutability::*;
pub use self::ViewItemInner::*; pub use self::Import::*;
pub use self::ViewPath::*;
pub use self::ItemEnum::*; pub use self::ItemEnum::*;
pub use self::Attribute::*; pub use self::Attribute::*;
pub use self::TyParamBound::*; pub use self::TyParamBound::*;
@ -315,6 +314,8 @@ impl Item {
#[derive(Clone, RustcEncodable, RustcDecodable, Show)] #[derive(Clone, RustcEncodable, RustcDecodable, Show)]
pub enum ItemEnum { pub enum ItemEnum {
ExternCrateItem(String, Option<String>),
ImportItem(Import),
StructItem(Struct), StructItem(Struct),
EnumItem(Enum), EnumItem(Enum),
FunctionItem(Function), FunctionItem(Function),
@ -324,8 +325,6 @@ pub enum ItemEnum {
ConstantItem(Constant), ConstantItem(Constant),
TraitItem(Trait), TraitItem(Trait),
ImplItem(Impl), ImplItem(Impl),
/// `use` and `extern crate`
ViewItemItem(ViewItem),
/// A method signature only. Used for required methods in traits (ie, /// A method signature only. Used for required methods in traits (ie,
/// non-default-methods). /// non-default-methods).
TyMethodItem(TyMethod), TyMethodItem(TyMethod),
@ -355,27 +354,21 @@ impl Clean<Item> for doctree::Module {
} else { } else {
"".to_string() "".to_string()
}; };
let mut foreigns = Vec::new(); let items: Vec<Item> =
for subforeigns in self.foreigns.clean(cx).into_iter() { self.extern_crates.iter().map(|x| x.clean(cx))
for foreign in subforeigns.into_iter() { .chain(self.imports.iter().flat_map(|x| x.clean(cx).into_iter()))
foreigns.push(foreign) .chain(self.structs.iter().map(|x| x.clean(cx)))
} .chain(self.enums.iter().map(|x| x.clean(cx)))
} .chain(self.fns.iter().map(|x| x.clean(cx)))
let items: Vec<Vec<Item> > = vec!( .chain(self.foreigns.iter().flat_map(|x| x.clean(cx).into_iter()))
self.structs.clean(cx), .chain(self.mods.iter().map(|x| x.clean(cx)))
self.enums.clean(cx), .chain(self.typedefs.iter().map(|x| x.clean(cx)))
self.fns.clean(cx), .chain(self.statics.iter().map(|x| x.clean(cx)))
foreigns, .chain(self.constants.iter().map(|x| x.clean(cx)))
self.mods.clean(cx), .chain(self.traits.iter().map(|x| x.clean(cx)))
self.typedefs.clean(cx), .chain(self.impls.iter().map(|x| x.clean(cx)))
self.statics.clean(cx), .chain(self.macros.iter().map(|x| x.clean(cx)))
self.constants.clean(cx), .collect();
self.traits.clean(cx),
self.impls.clean(cx),
self.view_items.clean(cx).into_iter()
.flat_map(|s| s.into_iter()).collect(),
self.macros.clean(cx),
);
// determine if we should display the inner contents or // determine if we should display the inner contents or
// the outer `mod` item for the source code. // the outer `mod` item for the source code.
@ -401,9 +394,7 @@ impl Clean<Item> for doctree::Module {
def_id: ast_util::local_def(self.id), def_id: ast_util::local_def(self.id),
inner: ModuleItem(Module { inner: ModuleItem(Module {
is_crate: self.is_crate, is_crate: self.is_crate,
items: items.iter() items: items
.flat_map(|x| x.iter().map(|x| (*x).clone()))
.collect(),
}) })
} }
} }
@ -2143,12 +2134,21 @@ impl Clean<Item> for doctree::Impl {
} }
} }
#[derive(Clone, RustcEncodable, RustcDecodable, Show)] impl Clean<Item> for doctree::ExternCrate {
pub struct ViewItem { fn clean(&self, cx: &DocContext) -> Item {
pub inner: ViewItemInner, Item {
name: None,
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
def_id: ast_util::local_def(0),
visibility: self.vis.clean(cx),
stability: None,
inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
}
}
} }
impl Clean<Vec<Item>> for ast::ViewItem { impl Clean<Vec<Item>> for doctree::Import {
fn clean(&self, cx: &DocContext) -> Vec<Item> { fn clean(&self, cx: &DocContext) -> Vec<Item> {
// We consider inlining the documentation of `pub use` statements, but we // We consider inlining the documentation of `pub use` statements, but we
// forcefully don't inline if this is not public or if the // forcefully don't inline if this is not public or if the
@ -2159,81 +2159,63 @@ impl Clean<Vec<Item>> for ast::ViewItem {
None => false, None => false,
} }
}); });
let convert = |&: node: &ast::ViewItem_| { let (mut ret, inner) = match self.node {
Item { ast::ViewPathGlob(ref p) => {
name: None, (vec![], GlobImport(resolve_use_source(cx, p.clean(cx), self.id)))
attrs: self.attrs.clean(cx),
source: self.span.clean(cx),
def_id: ast_util::local_def(0),
visibility: self.vis.clean(cx),
stability: None,
inner: ViewItemItem(ViewItem { inner: node.clean(cx) }),
} }
}; ast::ViewPathList(ref p, ref list) => {
let mut ret = Vec::new(); // Attempt to inline all reexported items, but be sure
match self.node { // to keep any non-inlineable reexports so they can be
ast::ViewItemUse(ref path) if !denied => { // listed in the documentation.
match path.node { let mut ret = vec![];
ast::ViewPathGlob(..) => ret.push(convert(&self.node)), let remaining = if !denied {
ast::ViewPathList(ref a, ref list, ref b) => { let mut remaining = vec![];
// Attempt to inline all reexported items, but be sure for path in list.iter() {
// to keep any non-inlineable reexports so they can be match inline::try_inline(cx, path.node.id(), None) {
// listed in the documentation. Some(items) => {
let remaining = list.iter().filter(|path| { ret.extend(items.into_iter());
match inline::try_inline(cx, path.node.id(), None) { }
Some(items) => { None => {
ret.extend(items.into_iter()); false remaining.push(path.clean(cx));
}
None => true,
} }
}).map(|a| a.clone()).collect::<Vec<ast::PathListItem>>();
if remaining.len() > 0 {
let path = ast::ViewPathList(a.clone(),
remaining,
b.clone());
let path = syntax::codemap::dummy_spanned(path);
ret.push(convert(&ast::ViewItemUse(P(path))));
} }
} }
ast::ViewPathSimple(ident, _, id) => { remaining
match inline::try_inline(cx, id, Some(ident)) { } else {
Some(items) => ret.extend(items.into_iter()), list.clean(cx)
None => ret.push(convert(&self.node)), };
} if remaining.is_empty() {
return ret;
}
(ret, ImportList(resolve_use_source(cx, p.clean(cx), self.id),
remaining))
}
ast::ViewPathSimple(i, ref p) => {
if !denied {
match inline::try_inline(cx, self.id, Some(i)) {
Some(items) => return items,
None => {}
} }
} }
(vec![], SimpleImport(i.clean(cx),
resolve_use_source(cx, p.clean(cx), self.id)))
} }
ref n => ret.push(convert(n)), };
} ret.push(Item {
return ret; name: None,
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
def_id: ast_util::local_def(0),
visibility: self.vis.clean(cx),
stability: None,
inner: ImportItem(inner)
});
ret
} }
} }
#[derive(Clone, RustcEncodable, RustcDecodable, Show)] #[derive(Clone, RustcEncodable, RustcDecodable, Show)]
pub enum ViewItemInner { pub enum Import {
ExternCrate(String, Option<String>, ast::NodeId),
Import(ViewPath)
}
impl Clean<ViewItemInner> for ast::ViewItem_ {
fn clean(&self, cx: &DocContext) -> ViewItemInner {
match self {
&ast::ViewItemExternCrate(ref i, ref p, ref id) => {
let string = match *p {
None => None,
Some((ref x, _)) => Some(x.get().to_string()),
};
ExternCrate(i.clean(cx), string, *id)
}
&ast::ViewItemUse(ref vp) => {
Import(vp.clean(cx))
}
}
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, Show)]
pub enum ViewPath {
// use source as str; // use source as str;
SimpleImport(String, ImportSource), SimpleImport(String, ImportSource),
// use source::*; // use source::*;
@ -2248,21 +2230,6 @@ pub struct ImportSource {
pub did: Option<ast::DefId>, pub did: Option<ast::DefId>,
} }
impl Clean<ViewPath> for ast::ViewPath {
fn clean(&self, cx: &DocContext) -> ViewPath {
match self.node {
ast::ViewPathSimple(ref i, ref p, id) =>
SimpleImport(i.clean(cx), resolve_use_source(cx, p.clean(cx), id)),
ast::ViewPathGlob(ref p, id) =>
GlobImport(resolve_use_source(cx, p.clean(cx), id)),
ast::ViewPathList(ref p, ref pl, id) => {
ImportList(resolve_use_source(cx, p.clean(cx), id),
pl.clean(cx))
}
}
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, Show)] #[derive(Clone, RustcEncodable, RustcDecodable, Show)]
pub struct ViewListIdent { pub struct ViewListIdent {
pub name: String, pub name: String,

View file

@ -25,6 +25,8 @@ pub struct Module {
pub attrs: Vec<ast::Attribute>, pub attrs: Vec<ast::Attribute>,
pub where_outer: Span, pub where_outer: Span,
pub where_inner: Span, pub where_inner: Span,
pub extern_crates: Vec<ExternCrate>,
pub imports: Vec<Import>,
pub structs: Vec<Struct>, pub structs: Vec<Struct>,
pub enums: Vec<Enum>, pub enums: Vec<Enum>,
pub fns: Vec<Function>, pub fns: Vec<Function>,
@ -38,7 +40,6 @@ pub struct Module {
pub stab: Option<attr::Stability>, pub stab: Option<attr::Stability>,
pub impls: Vec<Impl>, pub impls: Vec<Impl>,
pub foreigns: Vec<ast::ForeignMod>, pub foreigns: Vec<ast::ForeignMod>,
pub view_items: Vec<ast::ViewItem>,
pub macros: Vec<Macro>, pub macros: Vec<Macro>,
pub is_crate: bool, pub is_crate: bool,
} }
@ -53,6 +54,8 @@ impl Module {
where_outer: syntax::codemap::DUMMY_SP, where_outer: syntax::codemap::DUMMY_SP,
where_inner: syntax::codemap::DUMMY_SP, where_inner: syntax::codemap::DUMMY_SP,
attrs : Vec::new(), attrs : Vec::new(),
extern_crates: Vec::new(),
imports : Vec::new(),
structs : Vec::new(), structs : Vec::new(),
enums : Vec::new(), enums : Vec::new(),
fns : Vec::new(), fns : Vec::new(),
@ -62,7 +65,6 @@ impl Module {
constants : Vec::new(), constants : Vec::new(),
traits : Vec::new(), traits : Vec::new(),
impls : Vec::new(), impls : Vec::new(),
view_items : Vec::new(),
foreigns : Vec::new(), foreigns : Vec::new(),
macros : Vec::new(), macros : Vec::new(),
is_crate : false, is_crate : false,
@ -202,6 +204,22 @@ pub struct Macro {
pub stab: Option<attr::Stability>, pub stab: Option<attr::Stability>,
} }
pub struct ExternCrate {
pub name: Ident,
pub path: Option<String>,
pub vis: ast::Visibility,
pub attrs: Vec<ast::Attribute>,
pub whence: Span,
}
pub struct Import {
pub id: NodeId,
pub vis: ast::Visibility,
pub attrs: Vec<ast::Attribute>,
pub node: ast::ViewPath_,
pub whence: Span,
}
pub fn struct_type_from_def(sd: &ast::StructDef) -> StructType { pub fn struct_type_from_def(sd: &ast::StructDef) -> StructType {
if sd.ctor_id.is_some() { if sd.ctor_id.is_some() {
// We are in a tuple-struct // We are in a tuple-struct

View file

@ -617,7 +617,7 @@ impl fmt::Display for UnsafetySpace {
} }
} }
impl fmt::Display for clean::ViewPath { impl fmt::Display for clean::Import {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
clean::SimpleImport(ref name, ref src) => { clean::SimpleImport(ref name, ref src) => {

View file

@ -22,29 +22,31 @@ use clean;
#[derive(Copy, PartialEq, Clone)] #[derive(Copy, PartialEq, Clone)]
pub enum ItemType { pub enum ItemType {
Module = 0, Module = 0,
Struct = 1, ExternCrate = 1,
Enum = 2, Import = 2,
Function = 3, Struct = 3,
Typedef = 4, Enum = 4,
Static = 5, Function = 5,
Trait = 6, Typedef = 6,
Impl = 7, Static = 7,
ViewItem = 8, Trait = 8,
TyMethod = 9, Impl = 9,
Method = 10, TyMethod = 10,
StructField = 11, Method = 11,
Variant = 12, StructField = 12,
// we used to have ForeignFunction and ForeignStatic. they are retired now. Variant = 13,
Macro = 15, Macro = 14,
Primitive = 16, Primitive = 15,
AssociatedType = 17, AssociatedType = 16,
Constant = 18, Constant = 17,
} }
impl ItemType { impl ItemType {
pub fn from_item(item: &clean::Item) -> ItemType { pub fn from_item(item: &clean::Item) -> ItemType {
match item.inner { match item.inner {
clean::ModuleItem(..) => ItemType::Module, clean::ModuleItem(..) => ItemType::Module,
clean::ExternCrateItem(..) => ItemType::ExternCrate,
clean::ImportItem(..) => ItemType::Import,
clean::StructItem(..) => ItemType::Struct, clean::StructItem(..) => ItemType::Struct,
clean::EnumItem(..) => ItemType::Enum, clean::EnumItem(..) => ItemType::Enum,
clean::FunctionItem(..) => ItemType::Function, clean::FunctionItem(..) => ItemType::Function,
@ -53,7 +55,6 @@ impl ItemType {
clean::ConstantItem(..) => ItemType::Constant, clean::ConstantItem(..) => ItemType::Constant,
clean::TraitItem(..) => ItemType::Trait, clean::TraitItem(..) => ItemType::Trait,
clean::ImplItem(..) => ItemType::Impl, clean::ImplItem(..) => ItemType::Impl,
clean::ViewItemItem(..) => ItemType::ViewItem,
clean::TyMethodItem(..) => ItemType::TyMethod, clean::TyMethodItem(..) => ItemType::TyMethod,
clean::MethodItem(..) => ItemType::Method, clean::MethodItem(..) => ItemType::Method,
clean::StructFieldItem(..) => ItemType::StructField, clean::StructFieldItem(..) => ItemType::StructField,
@ -83,6 +84,8 @@ impl ItemType {
pub fn to_static_str(&self) -> &'static str { pub fn to_static_str(&self) -> &'static str {
match *self { match *self {
ItemType::Module => "mod", ItemType::Module => "mod",
ItemType::ExternCrate => "externcrate",
ItemType::Import => "import",
ItemType::Struct => "struct", ItemType::Struct => "struct",
ItemType::Enum => "enum", ItemType::Enum => "enum",
ItemType::Function => "fn", ItemType::Function => "fn",
@ -90,7 +93,6 @@ impl ItemType {
ItemType::Static => "static", ItemType::Static => "static",
ItemType::Trait => "trait", ItemType::Trait => "trait",
ItemType::Impl => "impl", ItemType::Impl => "impl",
ItemType::ViewItem => "viewitem",
ItemType::TyMethod => "tymethod", ItemType::TyMethod => "tymethod",
ItemType::Method => "method", ItemType::Method => "method",
ItemType::StructField => "structfield", ItemType::StructField => "structfield",

View file

@ -35,7 +35,7 @@
pub use self::ExternalLocation::*; pub use self::ExternalLocation::*;
use std::cell::RefCell; use std::cell::RefCell;
use std::cmp::Ordering::{self, Less, Greater, Equal}; use std::cmp::Ordering;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::default::Default; use std::default::Default;
use std::fmt; use std::fmt;
@ -1497,18 +1497,19 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
// the order of item types in the listing // the order of item types in the listing
fn reorder(ty: ItemType) -> u8 { fn reorder(ty: ItemType) -> u8 {
match ty { match ty {
ItemType::ViewItem => 0, ItemType::ExternCrate => 0,
ItemType::Primitive => 1, ItemType::Import => 1,
ItemType::Module => 2, ItemType::Primitive => 2,
ItemType::Macro => 3, ItemType::Module => 3,
ItemType::Struct => 4, ItemType::Macro => 4,
ItemType::Enum => 5, ItemType::Struct => 5,
ItemType::Constant => 6, ItemType::Enum => 6,
ItemType::Static => 7, ItemType::Constant => 7,
ItemType::Trait => 8, ItemType::Static => 8,
ItemType::Function => 9, ItemType::Trait => 9,
ItemType::Typedef => 10, ItemType::Function => 10,
_ => 11 + ty as u8, ItemType::Typedef => 12,
_ => 13 + ty as u8,
} }
} }
@ -1518,25 +1519,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
if ty1 == ty2 { if ty1 == ty2 {
return i1.name.cmp(&i2.name); return i1.name.cmp(&i2.name);
} }
(reorder(ty1), idx1).cmp(&(reorder(ty2), idx2))
let tycmp = reorder(ty1).cmp(&reorder(ty2));
if let Equal = tycmp {
// for reexports, `extern crate` takes precedence.
match (&i1.inner, &i2.inner) {
(&clean::ViewItemItem(ref a), &clean::ViewItemItem(ref b)) => {
match (&a.inner, &b.inner) {
(&clean::ExternCrate(..), _) => return Less,
(_, &clean::ExternCrate(..)) => return Greater,
_ => {}
}
}
(_, _) => {}
}
idx1.cmp(&idx2)
} else {
tycmp
}
} }
indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2)); indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2));
@ -1547,12 +1530,17 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
let myitem = &items[idx]; let myitem = &items[idx];
let myty = Some(shortty(myitem)); let myty = Some(shortty(myitem));
if myty != curty { if curty == Some(ItemType::ExternCrate) && myty == Some(ItemType::Import) {
// Put `extern crate` and `use` re-exports in the same section.
curty = myty;
} else if myty != curty {
if curty.is_some() { if curty.is_some() {
try!(write!(w, "</table>")); try!(write!(w, "</table>"));
} }
curty = myty; curty = myty;
let (short, name) = match myty.unwrap() { let (short, name) = match myty.unwrap() {
ItemType::ExternCrate |
ItemType::Import => ("reexports", "Reexports"),
ItemType::Module => ("modules", "Modules"), ItemType::Module => ("modules", "Modules"),
ItemType::Struct => ("structs", "Structs"), ItemType::Struct => ("structs", "Structs"),
ItemType::Enum => ("enums", "Enums"), ItemType::Enum => ("enums", "Enums"),
@ -1562,7 +1550,6 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
ItemType::Constant => ("constants", "Constants"), ItemType::Constant => ("constants", "Constants"),
ItemType::Trait => ("traits", "Traits"), ItemType::Trait => ("traits", "Traits"),
ItemType::Impl => ("impls", "Implementations"), ItemType::Impl => ("impls", "Implementations"),
ItemType::ViewItem => ("reexports", "Reexports"),
ItemType::TyMethod => ("tymethods", "Type Methods"), ItemType::TyMethod => ("tymethods", "Type Methods"),
ItemType::Method => ("methods", "Methods"), ItemType::Method => ("methods", "Methods"),
ItemType::StructField => ("fields", "Struct Fields"), ItemType::StructField => ("fields", "Struct Fields"),
@ -1578,28 +1565,25 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
} }
match myitem.inner { match myitem.inner {
clean::ViewItemItem(ref item) => { clean::ExternCrateItem(ref name, ref src) => {
match item.inner { match *src {
clean::ExternCrate(ref name, ref src, _) => { Some(ref src) => {
match *src { try!(write!(w, "<tr><td><code>{}extern crate \"{}\" as {};",
Some(ref src) => VisSpace(myitem.visibility),
try!(write!(w, "<tr><td><code>extern crate \"{}\" as {}", src.as_slice(),
src.as_slice(), name.as_slice()))
name.as_slice())),
None =>
try!(write!(w, "<tr><td><code>extern crate {}",
name.as_slice())),
}
try!(write!(w, ";</code></td></tr>"));
} }
None => {
clean::Import(ref import) => { try!(write!(w, "<tr><td><code>{}extern crate {};",
try!(write!(w, "<tr><td><code>{}{}</code></td></tr>", VisSpace(myitem.visibility), name.as_slice()))
VisSpace(myitem.visibility),
*import));
} }
} }
try!(write!(w, "</code></td></tr>"));
}
clean::ImportItem(ref import) => {
try!(write!(w, "<tr><td><code>{}{}</code></td></tr>",
VisSpace(myitem.visibility), *import));
} }
_ => { _ => {

View file

@ -245,7 +245,6 @@ nav.sub {
.content .highlighted.method { background-color: #c6afb3; } .content .highlighted.method { background-color: #c6afb3; }
.content .highlighted.tymethod { background-color: #c6afb3; } .content .highlighted.tymethod { background-color: #c6afb3; }
.content .highlighted.type { background-color: #c6afb3; } .content .highlighted.type { background-color: #c6afb3; }
.content .highlighted.ffi { background-color: #c6afb3; }
.docblock.short.nowrap { .docblock.short.nowrap {
display: block; display: block;
@ -365,7 +364,6 @@ p a:hover { text-decoration: underline; }
.content span.fn, .content a.fn, .block a.current.fn { color: #8c6067; } .content span.fn, .content a.fn, .block a.current.fn { color: #8c6067; }
.content span.method, .content a.method, .block a.current.method { color: #8c6067; } .content span.method, .content a.method, .block a.current.method { color: #8c6067; }
.content span.tymethod, .content a.tymethod, .block a.current.tymethod { color: #8c6067; } .content span.tymethod, .content a.tymethod, .block a.current.tymethod { color: #8c6067; }
.content span.ffi, .content a.ffi, .block a.current.ffi { color: #8c6067; }
.content .fnname { color: #8c6067; } .content .fnname { color: #8c6067; }
.search-input { .search-input {

View file

@ -555,6 +555,8 @@
// This mapping table should match the discriminants of // This mapping table should match the discriminants of
// `rustdoc::html::item_type::ItemType` type in Rust. // `rustdoc::html::item_type::ItemType` type in Rust.
var itemTypes = ["mod", var itemTypes = ["mod",
"externcrate",
"import",
"struct", "struct",
"enum", "enum",
"fn", "fn",
@ -562,13 +564,10 @@
"static", "static",
"trait", "trait",
"impl", "impl",
"viewitem",
"tymethod", "tymethod",
"method", "method",
"structfield", "structfield",
"variant", "variant",
"ffi", // retained for backward compatibility
"ffs", // retained for backward compatibility
"macro", "macro",
"primitive", "primitive",
"associatedtype", "associatedtype",

View file

@ -149,7 +149,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
} }
} }
clean::ViewItemItem(..) => { clean::ExternCrateItem(..) | clean::ImportItem(_) => {
if i.visibility != Some(ast::Public) { if i.visibility != Some(ast::Public) {
return None return None
} }

View file

@ -21,7 +21,7 @@ use syntax::ast::Public;
use clean::{Crate, Item, ModuleItem, Module, EnumItem, Enum}; use clean::{Crate, Item, ModuleItem, Module, EnumItem, Enum};
use clean::{ImplItem, Impl, Trait, TraitItem, TraitMethod, ProvidedMethod, RequiredMethod}; use clean::{ImplItem, Impl, Trait, TraitItem, TraitMethod, ProvidedMethod, RequiredMethod};
use clean::{TypeTraitItem, ViewItemItem, PrimitiveItem, Stability}; use clean::{TypeTraitItem, ExternCrateItem, ImportItem, PrimitiveItem, Stability};
use html::render::cache; use html::render::cache;
@ -199,7 +199,8 @@ fn summarize_item(item: &Item) -> (Counts, Option<ModuleSummary>) {
})) }))
} }
// no stability information for the following items: // no stability information for the following items:
ViewItemItem(_) | PrimitiveItem(_) => (Counts::zero(), None), ExternCrateItem(..) | ImportItem(_) |
PrimitiveItem(_) => (Counts::zero(), None),
_ => (item_counts, None) _ => (item_counts, None)
} }
} }

View file

@ -20,7 +20,6 @@ use syntax::ast_map;
use syntax::attr; use syntax::attr;
use syntax::attr::AttrMetaMethods; use syntax::attr::AttrMetaMethods;
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::ptr::P;
use rustc::middle::stability; use rustc::middle::stability;
@ -142,9 +141,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
m: &ast::Mod, m: &ast::Mod,
name: Option<ast::Ident>) -> Module { name: Option<ast::Ident>) -> Module {
let mut om = Module::new(name); let mut om = Module::new(name);
for item in m.view_items.iter() {
self.visit_view_item(item, &mut om);
}
om.where_outer = span; om.where_outer = span;
om.where_inner = m.inner; om.where_inner = m.inner;
om.attrs = attrs; om.attrs = attrs;
@ -157,68 +153,41 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
om om
} }
pub fn visit_view_item(&mut self, item: &ast::ViewItem, om: &mut Module) { fn visit_view_path(&mut self, path: ast::ViewPath_,
if item.vis != ast::Public {
return om.view_items.push(item.clone());
}
let please_inline = item.attrs.iter().any(|item| {
match item.meta_item_list() {
Some(list) => {
list.iter().any(|i| i.name().get() == "inline")
}
None => false,
}
});
let item = match item.node {
ast::ViewItemUse(ref vpath) => {
match self.visit_view_path(&**vpath, om, please_inline) {
None => return,
Some(path) => {
ast::ViewItem {
node: ast::ViewItemUse(path),
.. item.clone()
}
}
}
}
ast::ViewItemExternCrate(..) => item.clone()
};
om.view_items.push(item);
}
fn visit_view_path(&mut self, path: &ast::ViewPath,
om: &mut Module, om: &mut Module,
please_inline: bool) -> Option<P<ast::ViewPath>> { id: ast::NodeId,
match path.node { please_inline: bool) -> Option<ast::ViewPath_> {
ast::ViewPathSimple(dst, _, id) => { match path {
ast::ViewPathSimple(dst, base) => {
if self.resolve_id(id, Some(dst), false, om, please_inline) { if self.resolve_id(id, Some(dst), false, om, please_inline) {
return None None
} else {
Some(ast::ViewPathSimple(dst, base))
} }
} }
ast::ViewPathList(ref p, ref paths, ref b) => { ast::ViewPathList(p, paths) => {
let mut mine = Vec::new(); let mine = paths.into_iter().filter(|path| {
for path in paths.iter() { !self.resolve_id(path.node.id(), None, false, om,
if !self.resolve_id(path.node.id(), None, false, om, please_inline)
please_inline) { }).collect::<Vec<ast::PathListItem>>();
mine.push(path.clone());
}
}
if mine.len() == 0 { return None } if mine.len() == 0 {
return Some(P(::syntax::codemap::Spanned { None
node: ast::ViewPathList(p.clone(), mine, b.clone()), } else {
span: path.span, Some(ast::ViewPathList(p, mine))
})) }
} }
// these are feature gated anyway // these are feature gated anyway
ast::ViewPathGlob(_, id) => { ast::ViewPathGlob(base) => {
if self.resolve_id(id, None, true, om, please_inline) { if self.resolve_id(id, None, true, om, please_inline) {
return None None
} else {
Some(ast::ViewPathGlob(base))
} }
} }
} }
Some(P(path.clone()))
} }
fn resolve_id(&mut self, id: ast::NodeId, renamed: Option<ast::Ident>, fn resolve_id(&mut self, id: ast::NodeId, renamed: Option<ast::Ident>,
@ -242,9 +211,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
if glob { if glob {
match it.node { match it.node {
ast::ItemMod(ref m) => { ast::ItemMod(ref m) => {
for vi in m.view_items.iter() {
self.visit_view_item(vi, om);
}
for i in m.items.iter() { for i in m.items.iter() {
self.visit_item(&**i, None, om); self.visit_item(&**i, None, om);
} }
@ -268,6 +234,45 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
debug!("Visiting item {:?}", item); debug!("Visiting item {:?}", item);
let name = renamed.unwrap_or(item.ident); let name = renamed.unwrap_or(item.ident);
match item.node { match item.node {
ast::ItemExternCrate(ref p) => {
let path = match *p {
None => None,
Some((ref x, _)) => Some(x.get().to_string()),
};
om.extern_crates.push(ExternCrate {
name: name,
path: path,
vis: item.vis,
attrs: item.attrs.clone(),
whence: item.span,
})
}
ast::ItemUse(ref vpath) => {
let node = vpath.node.clone();
let node = if item.vis == ast::Public {
let please_inline = item.attrs.iter().any(|item| {
match item.meta_item_list() {
Some(list) => {
list.iter().any(|i| i.name().get() == "inline")
}
None => false,
}
});
match self.visit_view_path(node, om, item.id, please_inline) {
None => return,
Some(p) => p
}
} else {
node
};
om.imports.push(Import {
id: item.id,
vis: item.vis,
attrs: item.attrs.clone(),
node: node,
whence: item.span,
});
}
ast::ItemMod(ref m) => { ast::ItemMod(ref m) => {
om.mods.push(self.visit_mod_contents(item.span, om.mods.push(self.visit_mod_contents(item.span,
item.attrs.clone(), item.attrs.clone(),

View file

@ -53,7 +53,6 @@ pub use self::UnboxedClosureKind::*;
pub use self::UnOp::*; pub use self::UnOp::*;
pub use self::UnsafeSource::*; pub use self::UnsafeSource::*;
pub use self::VariantKind::*; pub use self::VariantKind::*;
pub use self::ViewItem_::*;
pub use self::ViewPath_::*; pub use self::ViewPath_::*;
pub use self::Visibility::*; pub use self::Visibility::*;
pub use self::PathParameters::*; pub use self::PathParameters::*;
@ -511,7 +510,6 @@ impl PartialEq for MetaItem_ {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
pub struct Block { pub struct Block {
pub view_items: Vec<ViewItem>,
pub stmts: Vec<P<Stmt>>, pub stmts: Vec<P<Stmt>>,
pub expr: Option<P<Expr>>, pub expr: Option<P<Expr>>,
pub id: NodeId, pub id: NodeId,
@ -1443,14 +1441,12 @@ pub struct Mod {
/// For `mod foo;`, the inner span ranges from the first token /// For `mod foo;`, the inner span ranges from the first token
/// to the last token in the external file. /// to the last token in the external file.
pub inner: Span, pub inner: Span,
pub view_items: Vec<ViewItem>,
pub items: Vec<P<Item>>, pub items: Vec<P<Item>>,
} }
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
pub struct ForeignMod { pub struct ForeignMod {
pub abi: Abi, pub abi: Abi,
pub view_items: Vec<ViewItem>,
pub items: Vec<P<ForeignItem>>, pub items: Vec<P<ForeignItem>>,
} }
@ -1509,44 +1505,13 @@ pub enum ViewPath_ {
/// or just /// or just
/// ///
/// `foo::bar::baz` (with `as baz` implicitly on the right) /// `foo::bar::baz` (with `as baz` implicitly on the right)
ViewPathSimple(Ident, Path, NodeId), ViewPathSimple(Ident, Path),
/// `foo::bar::*` /// `foo::bar::*`
ViewPathGlob(Path, NodeId), ViewPathGlob(Path),
/// `foo::bar::{a,b,c}` /// `foo::bar::{a,b,c}`
ViewPathList(Path, Vec<PathListItem> , NodeId) ViewPathList(Path, Vec<PathListItem>)
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
pub struct ViewItem {
pub node: ViewItem_,
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub span: Span,
}
impl ViewItem {
pub fn id(&self) -> NodeId {
match self.node {
ViewItemExternCrate(_, _, id) => id,
ViewItemUse(ref vp) => match vp.node {
ViewPathSimple(_, _, id) => id,
ViewPathGlob(_, id) => id,
ViewPathList(_, _, id) => id,
}
}
}
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
pub enum ViewItem_ {
/// Ident: name used to refer to this crate in the code
/// optional (InternedString,StrStyle): if present, this is a location
/// (containing arbitrary characters) from which to fetch the crate sources
/// For example, extern crate whatever = "github.com/rust-lang/rust"
ViewItemExternCrate(Ident, Option<(InternedString,StrStyle)>, NodeId),
ViewItemUse(P<ViewPath>),
} }
/// Meta-data associated with an item /// Meta-data associated with an item
@ -1668,6 +1633,12 @@ pub struct Item {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
pub enum Item_ { pub enum Item_ {
// Optional location (containing arbitrary characters) from which
// to fetch the crate sources.
// For example, extern crate whatever = "github.com/rust-lang/rust".
ItemExternCrate(Option<(InternedString, StrStyle)>),
ItemUse(P<ViewPath>),
ItemStatic(P<Ty>, Mutability, P<Expr>), ItemStatic(P<Ty>, Mutability, P<Expr>),
ItemConst(P<Ty>, P<Expr>), ItemConst(P<Ty>, P<Expr>),
ItemFn(P<FnDecl>, Unsafety, Abi, Generics, P<Block>), ItemFn(P<FnDecl>, Unsafety, Abi, Generics, P<Block>),
@ -1694,6 +1665,8 @@ pub enum Item_ {
impl Item_ { impl Item_ {
pub fn descriptive_variant(&self) -> &str { pub fn descriptive_variant(&self) -> &str {
match *self { match *self {
ItemExternCrate(..) => "extern crate",
ItemUse(..) => "use",
ItemStatic(..) => "static item", ItemStatic(..) => "static item",
ItemConst(..) => "constant item", ItemConst(..) => "constant item",
ItemFn(..) => "function", ItemFn(..) => "function",

View file

@ -107,7 +107,6 @@ pub fn path_to_string<PI: Iterator<Item=PathElem>>(path: PI) -> String {
#[derive(Copy, Show)] #[derive(Copy, Show)]
pub enum Node<'ast> { pub enum Node<'ast> {
NodeItem(&'ast Item), NodeItem(&'ast Item),
NodeViewItem(&'ast ViewItem),
NodeForeignItem(&'ast ForeignItem), NodeForeignItem(&'ast ForeignItem),
NodeTraitItem(&'ast TraitItem), NodeTraitItem(&'ast TraitItem),
NodeImplItem(&'ast ImplItem), NodeImplItem(&'ast ImplItem),
@ -134,7 +133,6 @@ enum MapEntry<'ast> {
/// All the node types, with a parent ID. /// All the node types, with a parent ID.
EntryItem(NodeId, &'ast Item), EntryItem(NodeId, &'ast Item),
EntryViewItem(NodeId, &'ast ViewItem),
EntryForeignItem(NodeId, &'ast ForeignItem), EntryForeignItem(NodeId, &'ast ForeignItem),
EntryTraitItem(NodeId, &'ast TraitItem), EntryTraitItem(NodeId, &'ast TraitItem),
EntryImplItem(NodeId, &'ast ImplItem), EntryImplItem(NodeId, &'ast ImplItem),
@ -169,7 +167,6 @@ impl<'ast> MapEntry<'ast> {
fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> { fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> {
match node { match node {
NodeItem(n) => EntryItem(p, n), NodeItem(n) => EntryItem(p, n),
NodeViewItem(n) => EntryViewItem(p, n),
NodeForeignItem(n) => EntryForeignItem(p, n), NodeForeignItem(n) => EntryForeignItem(p, n),
NodeTraitItem(n) => EntryTraitItem(p, n), NodeTraitItem(n) => EntryTraitItem(p, n),
NodeImplItem(n) => EntryImplItem(p, n), NodeImplItem(n) => EntryImplItem(p, n),
@ -188,7 +185,6 @@ impl<'ast> MapEntry<'ast> {
fn parent(self) -> Option<NodeId> { fn parent(self) -> Option<NodeId> {
Some(match self { Some(match self {
EntryItem(id, _) => id, EntryItem(id, _) => id,
EntryViewItem(id, _) => id,
EntryForeignItem(id, _) => id, EntryForeignItem(id, _) => id,
EntryTraitItem(id, _) => id, EntryTraitItem(id, _) => id,
EntryImplItem(id, _) => id, EntryImplItem(id, _) => id,
@ -208,7 +204,6 @@ impl<'ast> MapEntry<'ast> {
fn to_node(self) -> Option<Node<'ast>> { fn to_node(self) -> Option<Node<'ast>> {
Some(match self { Some(match self {
EntryItem(_, n) => NodeItem(n), EntryItem(_, n) => NodeItem(n),
EntryViewItem(_, n) => NodeViewItem(n),
EntryForeignItem(_, n) => NodeForeignItem(n), EntryForeignItem(_, n) => NodeForeignItem(n),
EntryTraitItem(_, n) => NodeTraitItem(n), EntryTraitItem(_, n) => NodeTraitItem(n),
EntryImplItem(_, n) => NodeImplItem(n), EntryImplItem(_, n) => NodeImplItem(n),
@ -341,13 +336,6 @@ impl<'ast> Map<'ast> {
} }
} }
pub fn expect_view_item(&self, id: NodeId) -> &'ast ViewItem {
match self.find(id) {
Some(NodeViewItem(view_item)) => view_item,
_ => panic!("expected view item, found {}", self.node_to_string(id))
}
}
pub fn expect_struct(&self, id: NodeId) -> &'ast StructDef { pub fn expect_struct(&self, id: NodeId) -> &'ast StructDef {
match self.find(id) { match self.find(id) {
Some(NodeItem(i)) => { Some(NodeItem(i)) => {
@ -533,7 +521,6 @@ impl<'ast> Map<'ast> {
pub fn opt_span(&self, id: NodeId) -> Option<Span> { pub fn opt_span(&self, id: NodeId) -> Option<Span> {
let sp = match self.find(id) { let sp = match self.find(id) {
Some(NodeItem(item)) => item.span, Some(NodeItem(item)) => item.span,
Some(NodeViewItem(item)) => item.span,
Some(NodeForeignItem(foreign_item)) => foreign_item.span, Some(NodeForeignItem(foreign_item)) => foreign_item.span,
Some(NodeTraitItem(trait_method)) => { Some(NodeTraitItem(trait_method)) => {
match *trait_method { match *trait_method {
@ -826,11 +813,6 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
self.parent = parent; self.parent = parent;
} }
fn visit_view_item(&mut self, item: &'ast ViewItem) {
self.insert(item.id(), NodeViewItem(item));
visit::walk_view_item(self, item);
}
fn visit_pat(&mut self, pat: &'ast Pat) { fn visit_pat(&mut self, pat: &'ast Pat) {
self.insert(pat.id, match pat.node { self.insert(pat.id, match pat.node {
// Note: this is at least *potentially* a pattern... // Note: this is at least *potentially* a pattern...
@ -904,7 +886,6 @@ pub fn map_crate<'ast, F: FoldOps>(forest: &'ast mut Forest, fold_ops: F) -> Map
let krate = mem::replace(&mut forest.krate, Crate { let krate = mem::replace(&mut forest.krate, Crate {
module: Mod { module: Mod {
inner: DUMMY_SP, inner: DUMMY_SP,
view_items: vec![],
items: vec![], items: vec![],
}, },
attrs: vec![], attrs: vec![],
@ -1036,7 +1017,6 @@ impl<'a> NodePrinter for pprust::State<'a> {
fn print_node(&mut self, node: &Node) -> IoResult<()> { fn print_node(&mut self, node: &Node) -> IoResult<()> {
match *node { match *node {
NodeItem(a) => self.print_item(&*a), NodeItem(a) => self.print_item(&*a),
NodeViewItem(a) => self.print_view_item(&*a),
NodeForeignItem(a) => self.print_foreign_item(&*a), NodeForeignItem(a) => self.print_foreign_item(&*a),
NodeTraitItem(a) => self.print_trait_method(&*a), NodeTraitItem(a) => self.print_trait_method(&*a),
NodeImplItem(a) => self.print_impl_item(&*a), NodeImplItem(a) => self.print_impl_item(&*a),
@ -1065,6 +1045,8 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
Some(NodeItem(item)) => { Some(NodeItem(item)) => {
let path_str = map.path_to_str_with_ident(id, item.ident); let path_str = map.path_to_str_with_ident(id, item.ident);
let item_str = match item.node { let item_str = match item.node {
ItemExternCrate(..) => "extern crate",
ItemUse(..) => "use",
ItemStatic(..) => "static", ItemStatic(..) => "static",
ItemConst(..) => "const", ItemConst(..) => "const",
ItemFn(..) => "fn", ItemFn(..) => "fn",
@ -1079,9 +1061,6 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
}; };
format!("{} {}{}", item_str, path_str, id_str) format!("{} {}{}", item_str, path_str, id_str)
} }
Some(NodeViewItem(item)) => {
format!("view item {}{}", pprust::view_item_to_string(&*item), id_str)
}
Some(NodeForeignItem(item)) => { Some(NodeForeignItem(item)) => {
let path_str = map.path_to_str_with_ident(id, item.ident); let path_str = map.path_to_str_with_ident(id, item.ident);
format!("foreign item {}{}", path_str, id_str) format!("foreign item {}{}", path_str, id_str)

View file

@ -410,37 +410,6 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
visit::walk_mod(self, module) visit::walk_mod(self, module)
} }
fn visit_view_item(&mut self, view_item: &ViewItem) {
if !self.pass_through_items {
if self.visited_outermost {
return;
} else {
self.visited_outermost = true;
}
}
match view_item.node {
ViewItemExternCrate(_, _, node_id) => {
self.operation.visit_id(node_id)
}
ViewItemUse(ref view_path) => {
match view_path.node {
ViewPathSimple(_, _, node_id) |
ViewPathGlob(_, node_id) => {
self.operation.visit_id(node_id)
}
ViewPathList(_, ref paths, node_id) => {
self.operation.visit_id(node_id);
for path in paths.iter() {
self.operation.visit_id(path.node.id())
}
}
}
}
}
visit::walk_view_item(self, view_item);
self.visited_outermost = false;
}
fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
self.operation.visit_id(foreign_item.id); self.operation.visit_id(foreign_item.id);
visit::walk_foreign_item(self, foreign_item) visit::walk_foreign_item(self, foreign_item)
@ -456,10 +425,24 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
} }
self.operation.visit_id(item.id); self.operation.visit_id(item.id);
if let ItemEnum(ref enum_definition, _) = item.node { match item.node {
for variant in enum_definition.variants.iter() { ItemUse(ref view_path) => {
self.operation.visit_id(variant.node.id) match view_path.node {
ViewPathSimple(_, _) |
ViewPathGlob(_) => {}
ViewPathList(_, ref paths) => {
for path in paths.iter() {
self.operation.visit_id(path.node.id())
}
}
}
} }
ItemEnum(ref enum_definition, _) => {
for variant in enum_definition.variants.iter() {
self.operation.visit_id(variant.node.id)
}
}
_ => {}
} }
visit::walk_item(self, item); visit::walk_item(self, item);
@ -662,37 +645,6 @@ pub fn walk_pat<F>(pat: &Pat, mut it: F) -> bool where F: FnMut(&Pat) -> bool {
walk_pat_(pat, &mut it) walk_pat_(pat, &mut it)
} }
pub trait EachViewItem {
fn each_view_item<F>(&self, f: F) -> bool where F: FnMut(&ast::ViewItem) -> bool;
}
struct EachViewItemData<F> where F: FnMut(&ast::ViewItem) -> bool {
callback: F,
}
impl<'v, F> Visitor<'v> for EachViewItemData<F> where F: FnMut(&ast::ViewItem) -> bool {
fn visit_view_item(&mut self, view_item: &ast::ViewItem) {
let _ = (self.callback)(view_item);
}
}
impl EachViewItem for ast::Crate {
fn each_view_item<F>(&self, f: F) -> bool where F: FnMut(&ast::ViewItem) -> bool {
let mut visit = EachViewItemData {
callback: f,
};
visit::walk_crate(&mut visit, self);
true
}
}
pub fn view_path_id(p: &ViewPath) -> NodeId {
match p.node {
ViewPathSimple(_, _, id) | ViewPathGlob(_, id)
| ViewPathList(_, _, id) => id
}
}
/// Returns true if the given struct def is tuple-like; i.e. that its fields /// Returns true if the given struct def is tuple-like; i.e. that its fields
/// are unnamed. /// are unnamed.
pub fn struct_def_is_tuple_like(struct_def: &ast::StructDef) -> bool { pub fn struct_def_is_tuple_like(struct_def: &ast::StructDef) -> bool {

View file

@ -63,28 +63,13 @@ pub fn strip_items<F>(krate: ast::Crate, in_cfg: F) -> ast::Crate where
ctxt.fold_crate(krate) ctxt.fold_crate(krate)
} }
fn filter_view_item<F>(cx: &mut Context<F>,
view_item: ast::ViewItem)
-> Option<ast::ViewItem> where
F: FnMut(&[ast::Attribute]) -> bool
{
if view_item_in_cfg(cx, &view_item) {
Some(view_item)
} else {
None
}
}
fn fold_mod<F>(cx: &mut Context<F>, fn fold_mod<F>(cx: &mut Context<F>,
ast::Mod {inner, ast::Mod {inner, items}: ast::Mod)
view_items, items}: ast::Mod) -> ast::Mod where -> ast::Mod where
F: FnMut(&[ast::Attribute]) -> bool F: FnMut(&[ast::Attribute]) -> bool
{ {
ast::Mod { ast::Mod {
inner: inner, inner: inner,
view_items: view_items.into_iter().filter_map(|a| {
filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
}).collect(),
items: items.into_iter().flat_map(|a| { items: items.into_iter().flat_map(|a| {
cx.fold_item(a).into_iter() cx.fold_item(a).into_iter()
}).collect() }).collect()
@ -104,15 +89,12 @@ fn filter_foreign_item<F>(cx: &mut Context<F>,
} }
fn fold_foreign_mod<F>(cx: &mut Context<F>, fn fold_foreign_mod<F>(cx: &mut Context<F>,
ast::ForeignMod {abi, view_items, items}: ast::ForeignMod) ast::ForeignMod {abi, items}: ast::ForeignMod)
-> ast::ForeignMod where -> ast::ForeignMod where
F: FnMut(&[ast::Attribute]) -> bool F: FnMut(&[ast::Attribute]) -> bool
{ {
ast::ForeignMod { ast::ForeignMod {
abi: abi, abi: abi,
view_items: view_items.into_iter().filter_map(|a| {
filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
}).collect(),
items: items.into_iter() items: items.into_iter()
.filter_map(|a| filter_foreign_item(cx, a)) .filter_map(|a| filter_foreign_item(cx, a))
.collect() .collect()
@ -216,18 +198,14 @@ fn retain_stmt<F>(cx: &mut Context<F>, stmt: &ast::Stmt) -> bool where
fn fold_block<F>(cx: &mut Context<F>, b: P<ast::Block>) -> P<ast::Block> where fn fold_block<F>(cx: &mut Context<F>, b: P<ast::Block>) -> P<ast::Block> where
F: FnMut(&[ast::Attribute]) -> bool F: FnMut(&[ast::Attribute]) -> bool
{ {
b.map(|ast::Block {id, view_items, stmts, expr, rules, span}| { b.map(|ast::Block {id, stmts, expr, rules, span}| {
let resulting_stmts: Vec<P<ast::Stmt>> = let resulting_stmts: Vec<P<ast::Stmt>> =
stmts.into_iter().filter(|a| retain_stmt(cx, &**a)).collect(); stmts.into_iter().filter(|a| retain_stmt(cx, &**a)).collect();
let resulting_stmts = resulting_stmts.into_iter() let resulting_stmts = resulting_stmts.into_iter()
.flat_map(|stmt| cx.fold_stmt(stmt).into_iter()) .flat_map(|stmt| cx.fold_stmt(stmt).into_iter())
.collect(); .collect();
let filtered_view_items = view_items.into_iter().filter_map(|a| {
filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
}).collect();
ast::Block { ast::Block {
id: id, id: id,
view_items: filtered_view_items,
stmts: resulting_stmts, stmts: resulting_stmts,
expr: expr.map(|x| cx.fold_expr(x)), expr: expr.map(|x| cx.fold_expr(x)),
rules: rules, rules: rules,
@ -267,12 +245,6 @@ fn foreign_item_in_cfg<F>(cx: &mut Context<F>, item: &ast::ForeignItem) -> bool
return (cx.in_cfg)(item.attrs.as_slice()); return (cx.in_cfg)(item.attrs.as_slice());
} }
fn view_item_in_cfg<F>(cx: &mut Context<F>, item: &ast::ViewItem) -> bool where
F: FnMut(&[ast::Attribute]) -> bool
{
return (cx.in_cfg)(item.attrs.as_slice());
}
fn trait_method_in_cfg<F>(cx: &mut Context<F>, meth: &ast::TraitItem) -> bool where fn trait_method_in_cfg<F>(cx: &mut Context<F>, meth: &ast::TraitItem) -> bool where
F: FnMut(&[ast::Attribute]) -> bool F: FnMut(&[ast::Attribute]) -> bool
{ {

View file

@ -97,7 +97,6 @@ pub trait AstBuilder {
expr: Option<P<ast::Expr>>) -> P<ast::Block>; expr: Option<P<ast::Expr>>) -> P<ast::Block>;
fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block>; fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block>;
fn block_all(&self, span: Span, fn block_all(&self, span: Span,
view_items: Vec<ast::ViewItem>,
stmts: Vec<P<ast::Stmt>>, stmts: Vec<P<ast::Stmt>>,
expr: Option<P<ast::Expr>>) -> P<ast::Block>; expr: Option<P<ast::Expr>>) -> P<ast::Block>;
@ -242,7 +241,7 @@ pub trait AstBuilder {
fn item_mod(&self, span: Span, inner_span: Span, fn item_mod(&self, span: Span, inner_span: Span,
name: Ident, attrs: Vec<ast::Attribute>, name: Ident, attrs: Vec<ast::Attribute>,
vi: Vec<ast::ViewItem> , items: Vec<P<ast::Item>> ) -> P<ast::Item>; items: Vec<P<ast::Item>>) -> P<ast::Item>;
fn item_static(&self, fn item_static(&self,
span: Span, span: Span,
@ -280,15 +279,15 @@ pub trait AstBuilder {
value: ast::Lit_) value: ast::Lit_)
-> P<ast::MetaItem>; -> P<ast::MetaItem>;
fn view_use(&self, sp: Span, fn item_use(&self, sp: Span,
vis: ast::Visibility, vp: P<ast::ViewPath>) -> ast::ViewItem; vis: ast::Visibility, vp: P<ast::ViewPath>) -> P<ast::Item>;
fn view_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> ast::ViewItem; fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P<ast::Item>;
fn view_use_simple_(&self, sp: Span, vis: ast::Visibility, fn item_use_simple_(&self, sp: Span, vis: ast::Visibility,
ident: ast::Ident, path: ast::Path) -> ast::ViewItem; ident: ast::Ident, path: ast::Path) -> P<ast::Item>;
fn view_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]) -> ast::ViewItem; path: Vec<ast::Ident>, imports: &[ast::Ident]) -> P<ast::Item>;
fn view_use_glob(&self, sp: Span, fn item_use_glob(&self, sp: Span,
vis: ast::Visibility, path: Vec<ast::Ident> ) -> ast::ViewItem; vis: ast::Visibility, path: Vec<ast::Ident>) -> P<ast::Item>;
} }
impl<'a> AstBuilder for ExtCtxt<'a> { impl<'a> AstBuilder for ExtCtxt<'a> {
@ -519,7 +518,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
fn block(&self, span: Span, stmts: Vec<P<ast::Stmt>>, fn block(&self, span: Span, stmts: Vec<P<ast::Stmt>>,
expr: Option<P<Expr>>) -> P<ast::Block> { expr: Option<P<Expr>>) -> P<ast::Block> {
self.block_all(span, Vec::new(), stmts, expr) self.block_all(span, stmts, expr)
} }
fn stmt_item(&self, sp: Span, item: P<ast::Item>) -> P<ast::Stmt> { fn stmt_item(&self, sp: Span, item: P<ast::Item>) -> P<ast::Stmt> {
@ -528,15 +527,13 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
} }
fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block> { fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block> {
self.block_all(expr.span, Vec::new(), Vec::new(), Some(expr)) self.block_all(expr.span, Vec::new(), Some(expr))
} }
fn block_all(&self, fn block_all(&self,
span: Span, span: Span,
view_items: Vec<ast::ViewItem>,
stmts: Vec<P<ast::Stmt>>, stmts: Vec<P<ast::Stmt>>,
expr: Option<P<ast::Expr>>) -> P<ast::Block> { expr: Option<P<ast::Expr>>) -> P<ast::Block> {
P(ast::Block { P(ast::Block {
view_items: view_items,
stmts: stmts, stmts: stmts,
expr: expr, expr: expr,
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
@ -1031,16 +1028,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
} }
fn item_mod(&self, span: Span, inner_span: Span, name: Ident, fn item_mod(&self, span: Span, inner_span: Span, name: Ident,
attrs: Vec<ast::Attribute> , attrs: Vec<ast::Attribute>,
vi: Vec<ast::ViewItem> , items: Vec<P<ast::Item>>) -> P<ast::Item> {
items: Vec<P<ast::Item>> ) -> P<ast::Item> {
self.item( self.item(
span, span,
name, name,
attrs, attrs,
ast::ItemMod(ast::Mod { ast::ItemMod(ast::Mod {
inner: inner_span, inner: inner_span,
view_items: vi,
items: items, items: items,
}) })
) )
@ -1101,47 +1096,47 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
P(respan(sp, ast::MetaNameValue(name, respan(sp, value)))) P(respan(sp, ast::MetaNameValue(name, respan(sp, value))))
} }
fn view_use(&self, sp: Span, fn item_use(&self, sp: Span,
vis: ast::Visibility, vp: P<ast::ViewPath>) -> ast::ViewItem { vis: ast::Visibility, vp: P<ast::ViewPath>) -> P<ast::Item> {
ast::ViewItem { P(ast::Item {
node: ast::ViewItemUse(vp), id: ast::DUMMY_NODE_ID,
attrs: Vec::new(), ident: special_idents::invalid,
attrs: vec![],
node: ast::ItemUse(vp),
vis: vis, vis: vis,
span: sp span: sp
} })
} }
fn view_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> ast::ViewItem { fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P<ast::Item> {
let last = path.segments.last().unwrap().identifier; let last = path.segments.last().unwrap().identifier;
self.view_use_simple_(sp, vis, last, path) self.item_use_simple_(sp, vis, last, path)
} }
fn view_use_simple_(&self, sp: Span, vis: ast::Visibility, fn item_use_simple_(&self, sp: Span, vis: ast::Visibility,
ident: ast::Ident, path: ast::Path) -> ast::ViewItem { ident: ast::Ident, path: ast::Path) -> P<ast::Item> {
self.view_use(sp, vis, self.item_use(sp, vis,
P(respan(sp, P(respan(sp,
ast::ViewPathSimple(ident, ast::ViewPathSimple(ident,
path, path))))
ast::DUMMY_NODE_ID))))
} }
fn view_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]) -> ast::ViewItem { 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, id: ast::DUMMY_NODE_ID })
}).collect(); }).collect();
self.view_use(sp, vis, self.item_use(sp, vis,
P(respan(sp, P(respan(sp,
ast::ViewPathList(self.path(sp, path), ast::ViewPathList(self.path(sp, path),
imports, imports))))
ast::DUMMY_NODE_ID))))
} }
fn view_use_glob(&self, sp: Span, fn item_use_glob(&self, sp: Span,
vis: ast::Visibility, path: Vec<ast::Ident> ) -> ast::ViewItem { vis: ast::Visibility, path: Vec<ast::Ident>) -> P<ast::Item> {
self.view_use(sp, vis, self.item_use(sp, vis,
P(respan(sp, P(respan(sp,
ast::ViewPathGlob(self.path(sp, path), ast::DUMMY_NODE_ID)))) ast::ViewPathGlob(self.path(sp, path)))))
} }
} }

View file

@ -1073,7 +1073,7 @@ impl<'a> MethodDef<'a> {
// <delegated expression referring to __self0_vi, et al.> // <delegated expression referring to __self0_vi, et al.>
// } // }
let arm_expr = cx.expr_block( let arm_expr = cx.expr_block(
cx.block_all(sp, Vec::new(), index_let_stmts, Some(arm_expr))); cx.block_all(sp, index_let_stmts, Some(arm_expr)));
// Builds arm: // Builds arm:
// _ => { let __self0_vi = ...; // _ => { let __self0_vi = ...;

View file

@ -206,7 +206,6 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
// wrap the if-let expr in a block // wrap the if-let expr in a block
let span = els.span; let span = els.span;
let blk = P(ast::Block { let blk = P(ast::Block {
view_items: vec![],
stmts: vec![], stmts: vec![],
expr: Some(P(els)), expr: Some(P(els)),
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
@ -799,8 +798,7 @@ pub fn expand_block(blk: P<Block>, fld: &mut MacroExpander) -> P<Block> {
// expand the elements of a block. // expand the elements of a block.
pub fn expand_block_elts(b: P<Block>, fld: &mut MacroExpander) -> P<Block> { pub fn expand_block_elts(b: P<Block>, fld: &mut MacroExpander) -> P<Block> {
b.map(|Block {id, view_items, stmts, expr, rules, span}| { b.map(|Block {id, stmts, expr, rules, span}| {
let new_view_items = view_items.into_iter().map(|x| fld.fold_view_item(x)).collect();
let new_stmts = stmts.into_iter().flat_map(|x| { let new_stmts = stmts.into_iter().flat_map(|x| {
// perform all pending renames // perform all pending renames
let renamed_stmt = { let renamed_stmt = {
@ -821,7 +819,6 @@ pub fn expand_block_elts(b: P<Block>, fld: &mut MacroExpander) -> P<Block> {
}); });
Block { Block {
id: fld.new_id(id), id: fld.new_id(id),
view_items: new_view_items,
stmts: new_stmts, stmts: new_stmts,
expr: new_expr, expr: new_expr,
rules: rules, rules: rules,

View file

@ -352,18 +352,11 @@ pub mod rt {
impl<'a> ExtParseUtils for ExtCtxt<'a> { impl<'a> ExtParseUtils for ExtCtxt<'a> {
fn parse_item(&self, s: String) -> P<ast::Item> { fn parse_item(&self, s: String) -> P<ast::Item> {
let res = parse::parse_item_from_source_str( parse::parse_item_from_source_str(
"<quote expansion>".to_string(), "<quote expansion>".to_string(),
s, s,
self.cfg(), self.cfg(),
self.parse_sess()); self.parse_sess()).expect("parse error")
match res {
Some(ast) => ast,
None => {
error!("parse error");
panic!()
}
}
} }
fn parse_stmt(&self, s: String) -> P<ast::Stmt> { fn parse_stmt(&self, s: String) -> P<ast::Stmt> {
@ -767,7 +760,6 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
vector.extend(mk_tts(cx, &tts[]).into_iter()); vector.extend(mk_tts(cx, &tts[]).into_iter());
let block = cx.expr_block( let block = cx.expr_block(
cx.block_all(sp, cx.block_all(sp,
Vec::new(),
vector, vector,
Some(cx.expr_ident(sp, id_ext("tt"))))); Some(cx.expr_ident(sp, id_ext("tt")))));
@ -778,18 +770,18 @@ fn expand_wrapper(cx: &ExtCtxt,
sp: Span, sp: Span,
cx_expr: P<ast::Expr>, cx_expr: P<ast::Expr>,
expr: P<ast::Expr>) -> P<ast::Expr> { expr: P<ast::Expr>) -> P<ast::Expr> {
let uses = [
&["syntax", "ext", "quote", "rt"],
].iter().map(|path| {
let path = path.iter().map(|s| s.to_string()).collect();
cx.view_use_glob(sp, ast::Inherited, ids_ext(path))
}).collect();
// Explicitly borrow to avoid moving from the invoker (#16992) // Explicitly borrow to avoid moving from the invoker (#16992)
let cx_expr_borrow = cx.expr_addr_of(sp, cx.expr_deref(sp, cx_expr)); let cx_expr_borrow = cx.expr_addr_of(sp, cx.expr_deref(sp, cx_expr));
let stmt_let_ext_cx = cx.stmt_let(sp, false, id_ext("ext_cx"), cx_expr_borrow); let stmt_let_ext_cx = cx.stmt_let(sp, false, id_ext("ext_cx"), cx_expr_borrow);
cx.expr_block(cx.block_all(sp, uses, vec!(stmt_let_ext_cx), Some(expr))) let stmts = [
&["syntax", "ext", "quote", "rt"],
].iter().map(|path| {
let path = path.iter().map(|s| s.to_string()).collect();
cx.stmt_item(sp, cx.item_use_glob(sp, ast::Inherited, ids_ext(path)))
}).chain(Some(stmt_let_ext_cx).into_iter()).collect();
cx.expr_block(cx.block_all(sp, stmts, Some(expr)))
} }
fn expand_parse_call(cx: &ExtCtxt, fn expand_parse_call(cx: &ExtCtxt,

View file

@ -64,7 +64,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
("rustc_diagnostic_macros", Active), ("rustc_diagnostic_macros", Active),
("unboxed_closures", Active), ("unboxed_closures", Active),
("import_shadowing", Active), ("import_shadowing", Removed),
("advanced_slice_patterns", Active), ("advanced_slice_patterns", Active),
("tuple_indexing", Accepted), ("tuple_indexing", Accepted),
("associated_types", Accepted), ("associated_types", Accepted),
@ -127,7 +127,6 @@ enum Status {
pub struct Features { pub struct Features {
pub unboxed_closures: bool, pub unboxed_closures: bool,
pub rustc_diagnostic_macros: bool, pub rustc_diagnostic_macros: bool,
pub import_shadowing: bool,
pub visible_private_types: bool, pub visible_private_types: bool,
pub quote: bool, pub quote: bool,
pub old_orphan_check: bool, pub old_orphan_check: bool,
@ -139,7 +138,6 @@ impl Features {
Features { Features {
unboxed_closures: false, unboxed_closures: false,
rustc_diagnostic_macros: false, rustc_diagnostic_macros: false,
import_shadowing: false,
visible_private_types: false, visible_private_types: false,
quote: false, quote: false,
old_orphan_check: false, old_orphan_check: false,
@ -228,22 +226,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
} }
} }
fn visit_view_item(&mut self, i: &ast::ViewItem) {
match i.node {
ast::ViewItemUse(..) => {}
ast::ViewItemExternCrate(..) => {
for attr in i.attrs.iter() {
if attr.check_name("plugin") {
self.gate_feature("plugin", attr.span,
"compiler plugins are experimental \
and possibly buggy");
}
}
}
}
visit::walk_view_item(self, i)
}
fn visit_item(&mut self, i: &ast::Item) { fn visit_item(&mut self, i: &ast::Item) {
for attr in i.attrs.iter() { for attr in i.attrs.iter() {
if attr.name() == "thread_local" { if attr.name() == "thread_local" {
@ -262,6 +244,14 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
} }
} }
match i.node { match i.node {
ast::ItemExternCrate(_) => {
if attr::contains_name(&i.attrs[], "plugin") {
self.gate_feature("plugin", i.span,
"compiler plugins are experimental \
and possibly buggy");
}
}
ast::ItemForeignMod(ref foreign_module) => { ast::ItemForeignMod(ref foreign_module) => {
if attr::contains_name(&i.attrs[], "link_args") { if attr::contains_name(&i.attrs[], "link_args") {
self.gate_feature("link_args", i.span, self.gate_feature("link_args", i.span,
@ -537,7 +527,6 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C
(Features { (Features {
unboxed_closures: cx.has_feature("unboxed_closures"), unboxed_closures: cx.has_feature("unboxed_closures"),
rustc_diagnostic_macros: cx.has_feature("rustc_diagnostic_macros"), rustc_diagnostic_macros: cx.has_feature("rustc_diagnostic_macros"),
import_shadowing: cx.has_feature("import_shadowing"),
visible_private_types: cx.has_feature("visible_private_types"), visible_private_types: cx.has_feature("visible_private_types"),
quote: cx.has_feature("quote"), quote: cx.has_feature("quote"),
old_orphan_check: cx.has_feature("old_orphan_check"), old_orphan_check: cx.has_feature("old_orphan_check"),

View file

@ -78,10 +78,6 @@ pub trait Folder : Sized {
noop_fold_view_path(view_path, self) noop_fold_view_path(view_path, self)
} }
fn fold_view_item(&mut self, vi: ViewItem) -> ViewItem {
noop_fold_view_item(vi, self)
}
fn fold_foreign_item(&mut self, ni: P<ForeignItem>) -> P<ForeignItem> { fn fold_foreign_item(&mut self, ni: P<ForeignItem>) -> P<ForeignItem> {
noop_fold_foreign_item(ni, self) noop_fold_foreign_item(ni, self)
} }
@ -349,16 +345,13 @@ pub fn noop_fold_meta_items<T: Folder>(meta_items: Vec<P<MetaItem>>, fld: &mut T
pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<ViewPath> { pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<ViewPath> {
view_path.map(|Spanned {node, span}| Spanned { view_path.map(|Spanned {node, span}| Spanned {
node: match node { node: match node {
ViewPathSimple(ident, path, node_id) => { ViewPathSimple(ident, path) => {
let id = fld.new_id(node_id); ViewPathSimple(ident, fld.fold_path(path))
ViewPathSimple(ident, fld.fold_path(path), id)
} }
ViewPathGlob(path, node_id) => { ViewPathGlob(path) => {
let id = fld.new_id(node_id); ViewPathGlob(fld.fold_path(path))
ViewPathGlob(fld.fold_path(path), id)
} }
ViewPathList(path, path_list_idents, node_id) => { ViewPathList(path, path_list_idents) => {
let id = fld.new_id(node_id);
ViewPathList(fld.fold_path(path), ViewPathList(fld.fold_path(path),
path_list_idents.move_map(|path_list_ident| { path_list_idents.move_map(|path_list_ident| {
Spanned { Spanned {
@ -373,8 +366,7 @@ pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<
}, },
span: fld.new_span(path_list_ident.span) span: fld.new_span(path_list_ident.span)
} }
}), }))
id)
} }
}, },
span: fld.new_span(span) span: fld.new_span(span)
@ -470,11 +462,10 @@ pub fn noop_fold_qpath<T: Folder>(qpath: P<QPath>, fld: &mut T) -> P<QPath> {
}) })
} }
pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, view_items, items}: ForeignMod, pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, items}: ForeignMod,
fld: &mut T) -> ForeignMod { fld: &mut T) -> ForeignMod {
ForeignMod { ForeignMod {
abi: abi, abi: abi,
view_items: view_items.move_map(|x| fld.fold_view_item(x)),
items: items.move_map(|x| fld.fold_foreign_item(x)), items: items.move_map(|x| fld.fold_foreign_item(x)),
} }
} }
@ -953,28 +944,9 @@ fn noop_fold_variant_arg<T: Folder>(VariantArg {id, ty}: VariantArg, folder: &mu
} }
} }
pub fn noop_fold_view_item<T: Folder>(ViewItem {node, attrs, vis, span}: ViewItem,
folder: &mut T) -> ViewItem {
ViewItem {
node: match node {
ViewItemExternCrate(ident, string, node_id) => {
ViewItemExternCrate(ident, string,
folder.new_id(node_id))
}
ViewItemUse(view_path) => {
ViewItemUse(folder.fold_view_path(view_path))
}
},
attrs: attrs.move_map(|a| folder.fold_attribute(a)),
vis: vis,
span: folder.new_span(span)
}
}
pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> { pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
b.map(|Block {id, view_items, stmts, expr, rules, span}| Block { b.map(|Block {id, stmts, expr, rules, span}| Block {
id: folder.new_id(id), id: folder.new_id(id),
view_items: view_items.move_map(|x| folder.fold_view_item(x)),
stmts: stmts.into_iter().flat_map(|s| folder.fold_stmt(s).into_iter()).collect(), stmts: stmts.into_iter().flat_map(|s| folder.fold_stmt(s).into_iter()).collect(),
expr: expr.map(|x| folder.fold_expr(x)), expr: expr.map(|x| folder.fold_expr(x)),
rules: rules, rules: rules,
@ -984,6 +956,10 @@ pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ { pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
match i { match i {
ItemExternCrate(string) => ItemExternCrate(string),
ItemUse(view_path) => {
ItemUse(folder.fold_view_path(view_path))
}
ItemStatic(t, m, e) => { ItemStatic(t, m, e) => {
ItemStatic(folder.fold_ty(t), m, folder.fold_expr(e)) ItemStatic(folder.fold_ty(t), m, folder.fold_expr(e))
} }
@ -1103,10 +1079,9 @@ pub fn noop_fold_type_method<T: Folder>(m: TypeMethod, fld: &mut T) -> TypeMetho
} }
} }
pub fn noop_fold_mod<T: Folder>(Mod {inner, view_items, items}: Mod, folder: &mut T) -> Mod { pub fn noop_fold_mod<T: Folder>(Mod {inner, items}: Mod, folder: &mut T) -> Mod {
Mod { Mod {
inner: folder.new_span(inner), inner: folder.new_span(inner),
view_items: view_items.move_map(|x| folder.fold_view_item(x)),
items: items.into_iter().flat_map(|x| folder.fold_item(x).into_iter()).collect(), items: items.into_iter().flat_map(|x| folder.fold_item(x).into_iter()).collect(),
} }
} }
@ -1137,9 +1112,8 @@ pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, config, mut exported_mac
} }
None => (ast::Mod { None => (ast::Mod {
inner: span, inner: span,
view_items: Vec::new(), items: vec![],
items: Vec::new(), }, vec![], span)
}, Vec::new(), span)
}; };
for def in exported_macros.iter_mut() { for def in exported_macros.iter_mut() {

View file

@ -757,11 +757,10 @@ mod test {
use attr::{first_attr_value_str_by_name, AttrMetaMethods}; use attr::{first_attr_value_str_by_name, AttrMetaMethods};
use parse::parser::Parser; use parse::parser::Parser;
use parse::token::{str_to_ident}; use parse::token::{str_to_ident};
use print::pprust::view_item_to_string; use print::pprust::item_to_string;
use ptr::P; use ptr::P;
use util::parser_testing::{string_to_tts, string_to_parser}; use util::parser_testing::{string_to_tts, string_to_parser};
use util::parser_testing::{string_to_expr, string_to_item}; use util::parser_testing::{string_to_expr, string_to_item, string_to_stmt};
use util::parser_testing::{string_to_stmt, string_to_view_item};
// produce a codemap::span // produce a codemap::span
fn sp(a: u32, b: u32) -> Span { fn sp(a: u32, b: u32) -> Span {
@ -1079,7 +1078,6 @@ mod test {
} }
}, },
P(ast::Block { P(ast::Block {
view_items: Vec::new(),
stmts: vec!(P(Spanned{ stmts: vec!(P(Spanned{
node: ast::StmtSemi(P(ast::Expr{ node: ast::StmtSemi(P(ast::Expr{
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
@ -1111,25 +1109,25 @@ mod test {
#[test] fn parse_use() { #[test] fn parse_use() {
let use_s = "use foo::bar::baz;"; let use_s = "use foo::bar::baz;";
let vitem = string_to_view_item(use_s.to_string()); let vitem = string_to_item(use_s.to_string()).unwrap();
let vitem_s = view_item_to_string(&vitem); let vitem_s = item_to_string(&*vitem);
assert_eq!(&vitem_s[], use_s); assert_eq!(&vitem_s[], use_s);
let use_s = "use foo::bar as baz;"; let use_s = "use foo::bar as baz;";
let vitem = string_to_view_item(use_s.to_string()); let vitem = string_to_item(use_s.to_string()).unwrap();
let vitem_s = view_item_to_string(&vitem); let vitem_s = item_to_string(&*vitem);
assert_eq!(&vitem_s[], use_s); assert_eq!(&vitem_s[], use_s);
} }
#[test] fn parse_extern_crate() { #[test] fn parse_extern_crate() {
let ex_s = "extern crate foo;"; let ex_s = "extern crate foo;";
let vitem = string_to_view_item(ex_s.to_string()); let vitem = string_to_item(ex_s.to_string()).unwrap();
let vitem_s = view_item_to_string(&vitem); let vitem_s = item_to_string(&*vitem);
assert_eq!(&vitem_s[], ex_s); assert_eq!(&vitem_s[], ex_s);
let ex_s = "extern crate \"foo\" as bar;"; let ex_s = "extern crate \"foo\" as bar;";
let vitem = string_to_view_item(ex_s.to_string()); let vitem = string_to_item(ex_s.to_string()).unwrap();
let vitem_s = view_item_to_string(&vitem); let vitem_s = item_to_string(&*vitem);
assert_eq!(&vitem_s[], ex_s); assert_eq!(&vitem_s[], ex_s);
} }

View file

@ -9,7 +9,6 @@
// except according to those terms. // except according to those terms.
pub use self::PathParsingMode::*; pub use self::PathParsingMode::*;
use self::ItemOrViewItem::*;
use abi; use abi;
use ast::{AssociatedType, BareFnTy}; use ast::{AssociatedType, BareFnTy};
@ -35,6 +34,7 @@ use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRet
use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic}; use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic};
use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst}; use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst};
use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy}; use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy};
use ast::{ItemExternCrate, ItemUse};
use ast::{LifetimeDef, Lit, Lit_}; use ast::{LifetimeDef, Lit, Lit_};
use ast::{LitBool, LitChar, LitByte, LitBinary}; use ast::{LitBool, LitChar, LitByte, LitBinary};
use ast::{LitStr, LitInt, Local, LocalLet}; use ast::{LitStr, LitInt, Local, LocalLet};
@ -59,7 +59,6 @@ use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath
use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq}; use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq};
use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind}; use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind};
use ast::{UnnamedField, UnsafeBlock}; use ast::{UnnamedField, UnsafeBlock};
use ast::{ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
use ast::{Visibility, WhereClause}; use ast::{Visibility, WhereClause};
use ast; use ast;
@ -122,14 +121,9 @@ pub enum BoundParsingMode {
Modified, Modified,
} }
enum ItemOrViewItem { /// The `Err` case indicates a failure to parse any kind of item.
/// Indicates a failure to parse any kind of item. The attributes are /// The attributes are returned.
/// returned. type MaybeItem = Result<P<Item>, Vec<Attribute>>;
IoviNone(Vec<Attribute>),
IoviItem(P<Item>),
IoviForeignItem(P<ForeignItem>),
IoviViewItem(ViewItem)
}
/// Possibly accept an `token::Interpolated` expression (a pre-parsed expression /// Possibly accept an `token::Interpolated` expression (a pre-parsed expression
@ -231,19 +225,6 @@ macro_rules! maybe_whole {
} }
} }
); );
(iovi $p:expr, $constructor:ident) => (
{
let found = match ($p).token {
token::Interpolated(token::$constructor(_)) => {
Some(($p).bump_and_get())
}
_ => None
};
if let Some(token::Interpolated(token::$constructor(x))) = found {
return IoviItem(x.clone());
}
}
);
(pair_empty $p:expr, $constructor:ident) => ( (pair_empty $p:expr, $constructor:ident) => (
{ {
let found = match ($p).token { let found = match ($p).token {
@ -269,14 +250,6 @@ fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
lhs lhs
} }
struct ParsedItemsAndViewItems {
attrs_remaining: Vec<Attribute>,
view_items: Vec<ViewItem>,
items: Vec<P<Item>> ,
foreign_items: Vec<P<ForeignItem>>
}
/* ident is handled by common.rs */ /* ident is handled by common.rs */
pub struct Parser<'a> { pub struct Parser<'a> {
@ -3032,8 +3005,7 @@ impl<'a> Parser<'a> {
let body = self.parse_expr(); let body = self.parse_expr();
let fakeblock = P(ast::Block { let fakeblock = P(ast::Block {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
view_items: Vec::new(), stmts: vec![],
stmts: Vec::new(),
span: body.span, span: body.span,
expr: Some(body), expr: Some(body),
rules: DefaultBlock, rules: DefaultBlock,
@ -3731,20 +3703,13 @@ impl<'a> Parser<'a> {
} else { } else {
let found_attrs = !item_attrs.is_empty(); let found_attrs = !item_attrs.is_empty();
let item_err = Parser::expected_item_err(&item_attrs[]); let item_err = Parser::expected_item_err(&item_attrs[]);
match self.parse_item_or_view_item(item_attrs, false) { match self.parse_item_(item_attrs, false) {
IoviItem(i) => { Ok(i) => {
let hi = i.span.hi; let hi = i.span.hi;
let decl = P(spanned(lo, hi, DeclItem(i))); let decl = P(spanned(lo, hi, DeclItem(i)));
P(spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID))) P(spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID)))
} }
IoviViewItem(vi) => { Err(_) => {
self.span_fatal(vi.span,
"view items must be declared at the top of the block");
}
IoviForeignItem(_) => {
self.fatal("foreign items are not allowed here");
}
IoviNone(_) => {
if found_attrs { if found_attrs {
let last_span = self.last_span; let last_span = self.last_span;
self.span_err(last_span, item_err); self.span_err(last_span, item_err);
@ -3794,36 +3759,17 @@ impl<'a> Parser<'a> {
(inner, self.parse_block_tail_(lo, DefaultBlock, next)) (inner, self.parse_block_tail_(lo, DefaultBlock, next))
} }
/// Precondition: already parsed the '{' or '#{' /// Precondition: already parsed the '{'.
/// I guess that also means "already parsed the 'impure'" if
/// necessary, and this should take a qualifier.
/// Some blocks start with "#{"...
fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> P<Block> { fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> P<Block> {
self.parse_block_tail_(lo, s, Vec::new()) self.parse_block_tail_(lo, s, Vec::new())
} }
/// Parse the rest of a block expression or function body /// Parse the rest of a block expression or function body
fn parse_block_tail_(&mut self, lo: BytePos, s: BlockCheckMode, fn parse_block_tail_(&mut self, lo: BytePos, s: BlockCheckMode,
first_item_attrs: Vec<Attribute> ) -> P<Block> { first_item_attrs: Vec<Attribute>) -> P<Block> {
let mut stmts = Vec::new(); let mut stmts = vec![];
let mut expr = None; let mut expr = None;
let mut attributes_box = first_item_attrs;
// wouldn't it be more uniform to parse view items only, here?
let ParsedItemsAndViewItems {
attrs_remaining,
view_items,
items,
..
} = self.parse_items_and_view_items(first_item_attrs,
false, false);
for item in items.into_iter() {
let span = item.span;
let decl = P(spanned(span.lo, span.hi, DeclItem(item)));
stmts.push(P(spanned(span.lo, span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID))));
}
let mut attributes_box = attrs_remaining;
while self.token != token::CloseDelim(token::Brace) { while self.token != token::CloseDelim(token::Brace) {
// parsing items even when they're not allowed lets us give // parsing items even when they're not allowed lets us give
@ -3932,7 +3878,6 @@ impl<'a> Parser<'a> {
let hi = self.span.hi; let hi = self.span.hi;
self.bump(); self.bump();
P(ast::Block { P(ast::Block {
view_items: view_items,
stmts: stmts, stmts: stmts,
expr: expr, expr: expr,
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
@ -5031,39 +4976,34 @@ impl<'a> Parser<'a> {
first_item_attrs: Vec<Attribute>, first_item_attrs: Vec<Attribute>,
inner_lo: BytePos) inner_lo: BytePos)
-> Mod { -> Mod {
// parse all of the items up to closing or an attribute. // Parse all of the items up to closing or an attribute.
// view items are legal here.
let ParsedItemsAndViewItems { let mut attrs = first_item_attrs;
attrs_remaining, attrs.push_all(&self.parse_outer_attributes()[]);
view_items, let mut items = vec![];
items: starting_items,
.. loop {
} = self.parse_items_and_view_items(first_item_attrs, true, true); match self.parse_item_(attrs, true) {
let mut items: Vec<P<Item>> = starting_items; Err(returned_attrs) => {
let attrs_remaining_len = attrs_remaining.len(); attrs = returned_attrs;
break
}
Ok(item) => {
attrs = self.parse_outer_attributes();
items.push(item)
}
}
}
// don't think this other loop is even necessary.... // don't think this other loop is even necessary....
let mut first = true;
while self.token != term { while self.token != term {
let mut attrs = self.parse_outer_attributes(); let mut attrs = mem::replace(&mut attrs, vec![]);
if first { attrs.push_all(&self.parse_outer_attributes()[]);
let mut tmp = attrs_remaining.clone(); debug!("parse_mod_items: parse_item_(attrs={:?})", attrs);
tmp.push_all(&attrs[]); match self.parse_item_(attrs, true /* macros allowed */) {
attrs = tmp; Ok(item) => items.push(item),
first = false; Err(_) => {
}
debug!("parse_mod_items: parse_item_or_view_item(attrs={:?})",
attrs);
match self.parse_item_or_view_item(attrs,
true /* macros allowed */) {
IoviItem(item) => items.push(item),
IoviViewItem(view_item) => {
self.span_fatal(view_item.span,
"view items must be declared at the top of \
the module");
}
_ => {
let token_str = self.this_token_to_string(); let token_str = self.this_token_to_string();
self.fatal(&format!("expected item, found `{}`", self.fatal(&format!("expected item, found `{}`",
token_str)[]) token_str)[])
@ -5071,16 +5011,15 @@ impl<'a> Parser<'a> {
} }
} }
if first && attrs_remaining_len > 0us { if !attrs.is_empty() {
// We parsed attributes for the first item but didn't find it // We parsed attributes for the first item but didn't find it
let last_span = self.last_span; let last_span = self.last_span;
self.span_err(last_span, self.span_err(last_span,
Parser::expected_item_err(&attrs_remaining[])); Parser::expected_item_err(&attrs[]));
} }
ast::Mod { ast::Mod {
inner: mk_sp(inner_lo, self.span.lo), inner: mk_sp(inner_lo, self.span.lo),
view_items: view_items,
items: items items: items
} }
} }
@ -5298,23 +5237,12 @@ impl<'a> Parser<'a> {
/// parse_foreign_items. /// parse_foreign_items.
fn parse_foreign_mod_items(&mut self, fn parse_foreign_mod_items(&mut self,
abi: abi::Abi, abi: abi::Abi,
first_item_attrs: Vec<Attribute> ) first_item_attrs: Vec<Attribute>)
-> ForeignMod { -> ForeignMod {
let ParsedItemsAndViewItems { let foreign_items = self.parse_foreign_items(first_item_attrs);
attrs_remaining,
view_items,
items: _,
foreign_items,
} = self.parse_foreign_items(first_item_attrs, true);
if !attrs_remaining.is_empty() {
let last_span = self.last_span;
self.span_err(last_span,
Parser::expected_item_err(&attrs_remaining[]));
}
assert!(self.token == token::CloseDelim(token::Brace)); assert!(self.token == token::CloseDelim(token::Brace));
ast::ForeignMod { ast::ForeignMod {
abi: abi, abi: abi,
view_items: view_items,
items: foreign_items items: foreign_items
} }
} }
@ -5329,8 +5257,8 @@ impl<'a> Parser<'a> {
fn parse_item_extern_crate(&mut self, fn parse_item_extern_crate(&mut self,
lo: BytePos, lo: BytePos,
visibility: Visibility, visibility: Visibility,
attrs: Vec<Attribute> ) attrs: Vec<Attribute>)
-> ItemOrViewItem { -> P<Item> {
let span = self.span; let span = self.span;
let (maybe_path, ident) = match self.token { let (maybe_path, ident) = match self.token {
@ -5374,12 +5302,13 @@ impl<'a> Parser<'a> {
} }
}; };
IoviViewItem(ast::ViewItem { let last_span = self.last_span;
node: ViewItemExternCrate(ident, maybe_path, ast::DUMMY_NODE_ID), self.mk_item(lo,
attrs: attrs, last_span.hi,
vis: visibility, ident,
span: mk_sp(lo, self.last_span.hi) ItemExternCrate(maybe_path),
}) visibility,
attrs)
} }
/// Parse `extern` for foreign ABIs /// Parse `extern` for foreign ABIs
@ -5396,8 +5325,8 @@ impl<'a> Parser<'a> {
lo: BytePos, lo: BytePos,
opt_abi: Option<abi::Abi>, opt_abi: Option<abi::Abi>,
visibility: Visibility, visibility: Visibility,
attrs: Vec<Attribute> ) attrs: Vec<Attribute>)
-> ItemOrViewItem { -> P<Item> {
self.expect(&token::OpenDelim(token::Brace)); self.expect(&token::OpenDelim(token::Brace));
@ -5408,13 +5337,12 @@ impl<'a> Parser<'a> {
self.expect(&token::CloseDelim(token::Brace)); self.expect(&token::CloseDelim(token::Brace));
let last_span = self.last_span; let last_span = self.last_span;
let item = self.mk_item(lo, self.mk_item(lo,
last_span.hi, last_span.hi,
special_idents::invalid, special_idents::invalid,
ItemForeignMod(m), ItemForeignMod(m),
visibility, visibility,
maybe_append(attrs, Some(inner))); maybe_append(attrs, Some(inner)))
return IoviItem(item);
} }
/// Parse type Foo = Bar; /// Parse type Foo = Bar;
@ -5556,14 +5484,12 @@ impl<'a> Parser<'a> {
} }
} }
/// Parse one of the items or view items allowed by the /// Parse one of the items allowed by the flags; on failure,
/// flags; on failure, return IoviNone. /// return `Err(remaining_attrs)`.
/// NB: this function no longer parses the items inside an /// NB: this function no longer parses the items inside an
/// extern crate. /// extern crate.
fn parse_item_or_view_item(&mut self, fn parse_item_(&mut self, attrs: Vec<Attribute>,
attrs: Vec<Attribute> , macros_allowed: bool) -> MaybeItem {
macros_allowed: bool)
-> ItemOrViewItem {
let nt_item = match self.token { let nt_item = match self.token {
token::Interpolated(token::NtItem(ref item)) => { token::Interpolated(token::NtItem(ref item)) => {
Some((**item).clone()) Some((**item).clone())
@ -5576,7 +5502,7 @@ impl<'a> Parser<'a> {
let mut attrs = attrs; let mut attrs = attrs;
mem::swap(&mut item.attrs, &mut attrs); mem::swap(&mut item.attrs, &mut attrs);
item.attrs.extend(attrs.into_iter()); item.attrs.extend(attrs.into_iter());
return IoviItem(P(item)); return Ok(P(item));
} }
None => {} None => {}
} }
@ -5585,22 +5511,24 @@ impl<'a> Parser<'a> {
let visibility = self.parse_visibility(); let visibility = self.parse_visibility();
// must be a view item:
if self.eat_keyword(keywords::Use) { if self.eat_keyword(keywords::Use) {
// USE ITEM (IoviViewItem) // USE ITEM
let view_item = self.parse_use(); let item_ = ItemUse(self.parse_view_path());
self.expect(&token::Semi); self.expect(&token::Semi);
return IoviViewItem(ast::ViewItem {
node: view_item, let last_span = self.last_span;
attrs: attrs, let item = self.mk_item(lo,
vis: visibility, last_span.hi,
span: mk_sp(lo, self.last_span.hi) token::special_idents::invalid,
}); item_,
visibility,
attrs);
return Ok(item);
} }
// either a view item or an item:
if self.eat_keyword(keywords::Extern) { if self.eat_keyword(keywords::Extern) {
if self.eat_keyword(keywords::Crate) { if self.eat_keyword(keywords::Crate) {
return self.parse_item_extern_crate(lo, visibility, attrs); return Ok(self.parse_item_extern_crate(lo, visibility, attrs));
} }
let opt_abi = self.parse_opt_abi(); let opt_abi = self.parse_opt_abi();
@ -5617,9 +5545,9 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} else if self.check(&token::OpenDelim(token::Brace)) { } else if self.check(&token::OpenDelim(token::Brace)) {
return self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs); return Ok(self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs));
} }
let span = self.span; let span = self.span;
@ -5634,7 +5562,6 @@ impl<'a> Parser<'a> {
self.span_err(span, "`virtual` structs have been removed from the language"); self.span_err(span, "`virtual` structs have been removed from the language");
} }
// the rest are all guaranteed to be items:
if self.token.is_keyword(keywords::Static) { if self.token.is_keyword(keywords::Static) {
// STATIC ITEM // STATIC ITEM
self.bump(); self.bump();
@ -5647,7 +5574,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.token.is_keyword(keywords::Const) { if self.token.is_keyword(keywords::Const) {
// CONST ITEM // CONST ITEM
@ -5665,7 +5592,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.token.is_keyword(keywords::Unsafe) && if self.token.is_keyword(keywords::Unsafe) &&
self.look_ahead(1us, |t| t.is_keyword(keywords::Trait)) self.look_ahead(1us, |t| t.is_keyword(keywords::Trait))
@ -5682,7 +5609,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.token.is_keyword(keywords::Unsafe) && if self.token.is_keyword(keywords::Unsafe) &&
self.look_ahead(1us, |t| t.is_keyword(keywords::Impl)) self.look_ahead(1us, |t| t.is_keyword(keywords::Impl))
@ -5698,7 +5625,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.token.is_keyword(keywords::Fn) { if self.token.is_keyword(keywords::Fn) {
// FUNCTION ITEM // FUNCTION ITEM
@ -5712,7 +5639,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.token.is_keyword(keywords::Unsafe) if self.token.is_keyword(keywords::Unsafe)
&& self.look_ahead(1us, |t| *t != token::OpenDelim(token::Brace)) { && self.look_ahead(1us, |t| *t != token::OpenDelim(token::Brace)) {
@ -5733,7 +5660,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.eat_keyword(keywords::Mod) { if self.eat_keyword(keywords::Mod) {
// MODULE ITEM // MODULE ITEM
@ -5746,7 +5673,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.eat_keyword(keywords::Type) { if self.eat_keyword(keywords::Type) {
// TYPE ITEM // TYPE ITEM
@ -5758,7 +5685,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.eat_keyword(keywords::Enum) { if self.eat_keyword(keywords::Enum) {
// ENUM ITEM // ENUM ITEM
@ -5770,7 +5697,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.eat_keyword(keywords::Trait) { if self.eat_keyword(keywords::Trait) {
// TRAIT ITEM // TRAIT ITEM
@ -5783,7 +5710,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.eat_keyword(keywords::Impl) { if self.eat_keyword(keywords::Impl) {
// IMPL ITEM // IMPL ITEM
@ -5795,7 +5722,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.eat_keyword(keywords::Struct) { if self.eat_keyword(keywords::Struct) {
// STRUCT ITEM // STRUCT ITEM
@ -5807,32 +5734,30 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility) self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility)
} }
/// Parse a foreign item; on failure, return IoviNone. /// Parse a foreign item; on failure, return `Err(remaining_attrs)`.
fn parse_foreign_item(&mut self, fn parse_foreign_item(&mut self, attrs: Vec<Attribute>)
attrs: Vec<Attribute> , -> Result<P<ForeignItem>, Vec<Attribute>> {
macros_allowed: bool)
-> ItemOrViewItem {
maybe_whole!(iovi self, NtItem);
let lo = self.span.lo; let lo = self.span.lo;
let visibility = self.parse_visibility(); let visibility = self.parse_visibility();
if self.token.is_keyword(keywords::Static) { if self.token.is_keyword(keywords::Static) {
// FOREIGN STATIC ITEM // FOREIGN STATIC ITEM
let item = self.parse_item_foreign_static(visibility, attrs); return Ok(self.parse_item_foreign_static(visibility, attrs));
return IoviForeignItem(item);
} }
if self.token.is_keyword(keywords::Fn) || self.token.is_keyword(keywords::Unsafe) { if self.token.is_keyword(keywords::Fn) || self.token.is_keyword(keywords::Unsafe) {
// FOREIGN FUNCTION ITEM // FOREIGN FUNCTION ITEM
let item = self.parse_item_foreign_fn(visibility, attrs); return Ok(self.parse_item_foreign_fn(visibility, attrs));
return IoviForeignItem(item);
} }
self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility)
// FIXME #5668: this will occur for a macro invocation:
let item = try!(self.parse_macro_use_or_failure(attrs, true, lo, visibility));
self.span_fatal(item.span, "macros cannot expand to foreign items");
} }
/// This is the fall-through for parsing items. /// This is the fall-through for parsing items.
@ -5842,7 +5767,7 @@ impl<'a> Parser<'a> {
macros_allowed: bool, macros_allowed: bool,
lo: BytePos, lo: BytePos,
visibility: Visibility visibility: Visibility
) -> ItemOrViewItem { ) -> MaybeItem {
if macros_allowed && !self.token.is_any_keyword() if macros_allowed && !self.token.is_any_keyword()
&& self.look_ahead(1, |t| *t == token::Not) && self.look_ahead(1, |t| *t == token::Not)
&& (self.look_ahead(2, |t| t.is_plain_ident()) && (self.look_ahead(2, |t| t.is_plain_ident())
@ -5891,7 +5816,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
attrs); attrs);
return IoviItem(item); return Ok(item);
} }
// FAILURE TO PARSE ITEM // FAILURE TO PARSE ITEM
@ -5902,7 +5827,7 @@ impl<'a> Parser<'a> {
self.span_fatal(last_span, "unmatched visibility `pub`"); self.span_fatal(last_span, "unmatched visibility `pub`");
} }
} }
return IoviNone(attrs); Err(attrs)
} }
pub fn parse_item_with_outer_attributes(&mut self) -> Option<P<Item>> { pub fn parse_item_with_outer_attributes(&mut self) -> Option<P<Item>> {
@ -5911,30 +5836,9 @@ impl<'a> Parser<'a> {
} }
pub fn parse_item(&mut self, attrs: Vec<Attribute>) -> Option<P<Item>> { pub fn parse_item(&mut self, attrs: Vec<Attribute>) -> Option<P<Item>> {
match self.parse_item_or_view_item(attrs, true) { self.parse_item_(attrs, true).ok()
IoviNone(_) => None,
IoviViewItem(_) =>
self.fatal("view items are not allowed here"),
IoviForeignItem(_) =>
self.fatal("foreign items are not allowed here"),
IoviItem(item) => Some(item)
}
} }
/// Parse a ViewItem, e.g. `use foo::bar` or `extern crate foo`
pub fn parse_view_item(&mut self, attrs: Vec<Attribute>) -> ViewItem {
match self.parse_item_or_view_item(attrs, false) {
IoviViewItem(vi) => vi,
_ => self.fatal("expected `use` or `extern crate`"),
}
}
/// Parse, e.g., "use a::b::{z,y}"
fn parse_use(&mut self) -> ViewItem_ {
return ViewItemUse(self.parse_view_path());
}
/// Matches view_path : MOD? non_global_path as IDENT /// Matches view_path : MOD? non_global_path as IDENT
/// | MOD? non_global_path MOD_SEP LBRACE RBRACE /// | MOD? non_global_path MOD_SEP LBRACE RBRACE
/// | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE /// | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE
@ -5959,8 +5863,7 @@ impl<'a> Parser<'a> {
global: false, global: false,
segments: Vec::new() segments: Vec::new()
}; };
return P(spanned(lo, self.span.hi, return P(spanned(lo, self.span.hi, ViewPathList(path, idents)));
ViewPathList(path, idents, ast::DUMMY_NODE_ID)));
} }
let first_ident = self.parse_ident(); let first_ident = self.parse_ident();
@ -5994,8 +5897,7 @@ impl<'a> Parser<'a> {
} }
}).collect() }).collect()
}; };
return P(spanned(lo, self.span.hi, return P(spanned(lo, self.span.hi, ViewPathList(path, idents)));
ViewPathList(path, idents, ast::DUMMY_NODE_ID)));
} }
// foo::bar::* // foo::bar::*
@ -6011,8 +5913,7 @@ impl<'a> Parser<'a> {
} }
}).collect() }).collect()
}; };
return P(spanned(lo, self.span.hi, return P(spanned(lo, self.span.hi, ViewPathGlob(path)));
ViewPathGlob(path, ast::DUMMY_NODE_ID)));
} }
_ => break _ => break
@ -6033,136 +5934,39 @@ impl<'a> Parser<'a> {
if self.eat_keyword(keywords::As) { if self.eat_keyword(keywords::As) {
rename_to = self.parse_ident() rename_to = self.parse_ident()
} }
P(spanned(lo, P(spanned(lo, self.last_span.hi, ViewPathSimple(rename_to, path)))
self.last_span.hi,
ViewPathSimple(rename_to, path, ast::DUMMY_NODE_ID)))
}
/// Parses a sequence of items. Stops when it finds program
/// text that can't be parsed as an item
/// - mod_items uses extern_mod_allowed = true
/// - block_tail_ uses extern_mod_allowed = false
fn parse_items_and_view_items(&mut self,
first_item_attrs: Vec<Attribute> ,
mut extern_mod_allowed: bool,
macros_allowed: bool)
-> ParsedItemsAndViewItems {
let mut attrs = first_item_attrs;
attrs.push_all(&self.parse_outer_attributes()[]);
// First, parse view items.
let mut view_items : Vec<ast::ViewItem> = Vec::new();
let mut items = Vec::new();
// I think this code would probably read better as a single
// loop with a mutable three-state-variable (for extern crates,
// view items, and regular items) ... except that because
// of macros, I'd like to delay that entire check until later.
loop {
match self.parse_item_or_view_item(attrs, macros_allowed) {
IoviNone(attrs) => {
return ParsedItemsAndViewItems {
attrs_remaining: attrs,
view_items: view_items,
items: items,
foreign_items: Vec::new()
}
}
IoviViewItem(view_item) => {
match view_item.node {
ViewItemUse(..) => {
// `extern crate` must precede `use`.
extern_mod_allowed = false;
}
ViewItemExternCrate(..) if !extern_mod_allowed => {
self.span_err(view_item.span,
"\"extern crate\" declarations are \
not allowed here");
}
ViewItemExternCrate(..) => {}
}
view_items.push(view_item);
}
IoviItem(item) => {
items.push(item);
attrs = self.parse_outer_attributes();
break;
}
IoviForeignItem(_) => {
panic!();
}
}
attrs = self.parse_outer_attributes();
}
// Next, parse items.
loop {
match self.parse_item_or_view_item(attrs, macros_allowed) {
IoviNone(returned_attrs) => {
attrs = returned_attrs;
break
}
IoviViewItem(view_item) => {
attrs = self.parse_outer_attributes();
self.span_err(view_item.span,
"`use` and `extern crate` declarations must precede items");
}
IoviItem(item) => {
attrs = self.parse_outer_attributes();
items.push(item)
}
IoviForeignItem(_) => {
panic!();
}
}
}
ParsedItemsAndViewItems {
attrs_remaining: attrs,
view_items: view_items,
items: items,
foreign_items: Vec::new()
}
} }
/// Parses a sequence of foreign items. Stops when it finds program /// Parses a sequence of foreign items. Stops when it finds program
/// text that can't be parsed as an item /// text that can't be parsed as an item
fn parse_foreign_items(&mut self, first_item_attrs: Vec<Attribute> , fn parse_foreign_items(&mut self, first_item_attrs: Vec<Attribute>)
macros_allowed: bool) -> Vec<P<ForeignItem>> {
-> ParsedItemsAndViewItems {
let mut attrs = first_item_attrs; let mut attrs = first_item_attrs;
attrs.push_all(&self.parse_outer_attributes()[]); attrs.push_all(&self.parse_outer_attributes()[]);
let mut foreign_items = Vec::new(); let mut foreign_items = Vec::new();
loop { loop {
match self.parse_foreign_item(attrs, macros_allowed) { match self.parse_foreign_item(attrs) {
IoviNone(returned_attrs) => { Ok(foreign_item) => {
foreign_items.push(foreign_item);
}
Err(returned_attrs) => {
if self.check(&token::CloseDelim(token::Brace)) { if self.check(&token::CloseDelim(token::Brace)) {
attrs = returned_attrs; attrs = returned_attrs;
break break
} }
self.unexpected(); self.unexpected();
},
IoviViewItem(view_item) => {
// I think this can't occur:
self.span_err(view_item.span,
"`use` and `extern crate` declarations must precede items");
}
IoviItem(item) => {
// FIXME #5668: this will occur for a macro invocation:
self.span_fatal(item.span, "macros cannot expand to foreign items");
}
IoviForeignItem(foreign_item) => {
foreign_items.push(foreign_item);
} }
} }
attrs = self.parse_outer_attributes(); attrs = self.parse_outer_attributes();
} }
ParsedItemsAndViewItems { if !attrs.is_empty() {
attrs_remaining: attrs, let last_span = self.last_span;
view_items: Vec::new(), self.span_err(last_span,
items: Vec::new(), Parser::expected_item_err(&attrs[]));
foreign_items: foreign_items
} }
foreign_items
} }
/// Parses a source module as a crate. This is the main /// Parses a source module as a crate. This is the main

View file

@ -337,10 +337,6 @@ pub fn item_to_string(i: &ast::Item) -> String {
$to_string(|s| s.print_item(i)) $to_string(|s| s.print_item(i))
} }
pub fn view_item_to_string(i: &ast::ViewItem) -> String {
$to_string(|s| s.print_view_item(i))
}
pub fn generics_to_string(generics: &ast::Generics) -> String { pub fn generics_to_string(generics: &ast::Generics) -> String {
$to_string(|s| s.print_generics(generics)) $to_string(|s| s.print_generics(generics))
} }
@ -638,9 +634,6 @@ impl<'a> State<'a> {
pub fn print_mod(&mut self, _mod: &ast::Mod, pub fn print_mod(&mut self, _mod: &ast::Mod,
attrs: &[ast::Attribute]) -> IoResult<()> { attrs: &[ast::Attribute]) -> IoResult<()> {
try!(self.print_inner_attributes(attrs)); try!(self.print_inner_attributes(attrs));
for vitem in _mod.view_items.iter() {
try!(self.print_view_item(vitem));
}
for item in _mod.items.iter() { for item in _mod.items.iter() {
try!(self.print_item(&**item)); try!(self.print_item(&**item));
} }
@ -650,9 +643,6 @@ impl<'a> State<'a> {
pub fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, pub fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod,
attrs: &[ast::Attribute]) -> IoResult<()> { attrs: &[ast::Attribute]) -> IoResult<()> {
try!(self.print_inner_attributes(attrs)); try!(self.print_inner_attributes(attrs));
for vitem in nmod.view_items.iter() {
try!(self.print_view_item(vitem));
}
for item in nmod.items.iter() { for item in nmod.items.iter() {
try!(self.print_foreign_item(&**item)); try!(self.print_foreign_item(&**item));
} }
@ -809,6 +799,28 @@ impl<'a> State<'a> {
try!(self.print_outer_attributes(&item.attrs[])); try!(self.print_outer_attributes(&item.attrs[]));
try!(self.ann.pre(self, NodeItem(item))); try!(self.ann.pre(self, NodeItem(item)));
match item.node { match item.node {
ast::ItemExternCrate(ref optional_path) => {
try!(self.head(&visibility_qualified(item.vis,
"extern crate")[]));
for &(ref p, style) in optional_path.iter() {
try!(self.print_string(p.get(), style));
try!(space(&mut self.s));
try!(word(&mut self.s, "as"));
try!(space(&mut self.s));
}
try!(self.print_ident(item.ident));
try!(word(&mut self.s, ";"));
try!(self.end()); // end inner head-block
try!(self.end()); // end outer head-block
}
ast::ItemUse(ref vp) => {
try!(self.head(&visibility_qualified(item.vis,
"use")[]));
try!(self.print_view_path(&**vp));
try!(word(&mut self.s, ";"));
try!(self.end()); // end inner head-block
try!(self.end()); // end outer head-block
}
ast::ItemStatic(ref ty, m, ref expr) => { ast::ItemStatic(ref ty, m, ref expr) => {
try!(self.head(&visibility_qualified(item.vis, try!(self.head(&visibility_qualified(item.vis,
"static")[])); "static")[]));
@ -1380,9 +1392,6 @@ impl<'a> State<'a> {
try!(self.print_inner_attributes(attrs)); try!(self.print_inner_attributes(attrs));
for vi in blk.view_items.iter() {
try!(self.print_view_item(vi));
}
for st in blk.stmts.iter() { for st in blk.stmts.iter() {
try!(self.print_stmt(&**st)); try!(self.print_stmt(&**st));
} }
@ -2577,7 +2586,7 @@ impl<'a> State<'a> {
pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> { pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> {
match vp.node { match vp.node {
ast::ViewPathSimple(ident, ref path, _) => { ast::ViewPathSimple(ident, ref path) => {
try!(self.print_path(path, false)); try!(self.print_path(path, false));
// FIXME(#6993) can't compare identifiers directly here // FIXME(#6993) can't compare identifiers directly here
@ -2591,12 +2600,12 @@ impl<'a> State<'a> {
Ok(()) Ok(())
} }
ast::ViewPathGlob(ref path, _) => { ast::ViewPathGlob(ref path) => {
try!(self.print_path(path, false)); try!(self.print_path(path, false));
word(&mut self.s, "::*") word(&mut self.s, "::*")
} }
ast::ViewPathList(ref path, ref idents, _) => { ast::ViewPathList(ref path, ref idents) => {
if path.segments.is_empty() { if path.segments.is_empty() {
try!(word(&mut self.s, "{")); try!(word(&mut self.s, "{"));
} else { } else {
@ -2618,33 +2627,6 @@ impl<'a> State<'a> {
} }
} }
pub fn print_view_item(&mut self, item: &ast::ViewItem) -> IoResult<()> {
try!(self.hardbreak_if_not_bol());
try!(self.maybe_print_comment(item.span.lo));
try!(self.print_outer_attributes(&item.attrs[]));
try!(self.print_visibility(item.vis));
match item.node {
ast::ViewItemExternCrate(id, ref optional_path, _) => {
try!(self.head("extern crate"));
for &(ref p, style) in optional_path.iter() {
try!(self.print_string(p.get(), style));
try!(space(&mut self.s));
try!(word(&mut self.s, "as"));
try!(space(&mut self.s));
}
try!(self.print_ident(id));
}
ast::ViewItemUse(ref vp) => {
try!(self.head("use"));
try!(self.print_view_path(&**vp));
}
}
try!(word(&mut self.s, ";"));
try!(self.end()); // end inner head-block
self.end() // end outer head-block
}
pub fn print_mutability(&mut self, pub fn print_mutability(&mut self,
mutbl: ast::Mutability) -> IoResult<()> { mutbl: ast::Mutability) -> IoResult<()> {
match mutbl { match mutbl {

View file

@ -20,8 +20,6 @@ use parse::token;
use ptr::P; use ptr::P;
use util::small_vector::SmallVector; use util::small_vector::SmallVector;
use std::mem;
pub fn maybe_inject_crates_ref(krate: ast::Crate, alt_std_name: Option<String>) pub fn maybe_inject_crates_ref(krate: ast::Crate, alt_std_name: Option<String>)
-> ast::Crate { -> ast::Crate {
if use_std(&krate) { if use_std(&krate) {
@ -60,20 +58,16 @@ impl<'a> fold::Folder for StandardLibraryInjector<'a> {
None => token::intern_and_get_ident("std"), None => token::intern_and_get_ident("std"),
}; };
let mut vis = vec!(ast::ViewItem { krate.module.items.insert(0, P(ast::Item {
node: ast::ViewItemExternCrate(token::str_to_ident("std"), id: ast::DUMMY_NODE_ID,
Some((actual_crate_name, ast::CookedStr)), ident: token::str_to_ident("std"),
ast::DUMMY_NODE_ID),
attrs: vec!( attrs: vec!(
attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_word_item( attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_word_item(
InternedString::new("macro_use")))), InternedString::new("macro_use")))),
node: ast::ItemExternCrate(Some((actual_crate_name, ast::CookedStr))),
vis: ast::Inherited, vis: ast::Inherited,
span: DUMMY_SP span: DUMMY_SP
}); }));
// `extern crate` must be precede `use` items
mem::swap(&mut vis, &mut krate.module.view_items);
krate.module.view_items.extend(vis.into_iter());
// don't add #![no_std] here, that will block the prelude injection later. // don't add #![no_std] here, that will block the prelude injection later.
// Add it during the prelude injection instead. // Add it during the prelude injection instead.
@ -123,7 +117,7 @@ impl<'a> fold::Folder for PreludeInjector<'a> {
} }
} }
fn fold_mod(&mut self, ast::Mod {inner, view_items, items}: ast::Mod) -> ast::Mod { fn fold_mod(&mut self, mut mod_: ast::Mod) -> ast::Mod {
let prelude_path = ast::Path { let prelude_path = ast::Path {
span: DUMMY_SP, span: DUMMY_SP,
global: false, global: false,
@ -143,18 +137,11 @@ impl<'a> fold::Folder for PreludeInjector<'a> {
], ],
}; };
let (crates, uses): (Vec<_>, _) = view_items.iter().cloned().partition(|x| { let vp = P(codemap::dummy_spanned(ast::ViewPathGlob(prelude_path)));
match x.node { mod_.items.insert(0, P(ast::Item {
ast::ViewItemExternCrate(..) => true, id: ast::DUMMY_NODE_ID,
_ => false, ident: special_idents::invalid,
} node: ast::ItemUse(vp),
});
// add prelude after any `extern crate` but before any `use`
let mut view_items = crates;
let vp = P(codemap::dummy_spanned(ast::ViewPathGlob(prelude_path, ast::DUMMY_NODE_ID)));
view_items.push(ast::ViewItem {
node: ast::ViewItemUse(vp),
attrs: vec![ast::Attribute { attrs: vec![ast::Attribute {
span: DUMMY_SP, span: DUMMY_SP,
node: ast::Attribute_ { node: ast::Attribute_ {
@ -170,14 +157,9 @@ impl<'a> fold::Folder for PreludeInjector<'a> {
}], }],
vis: ast::Inherited, vis: ast::Inherited,
span: DUMMY_SP, span: DUMMY_SP,
}); }));
view_items.extend(uses.into_iter());
fold::noop_fold_mod(ast::Mod { fold::noop_fold_mod(mod_, self)
inner: inner,
view_items: view_items,
items: items
}, self)
} }
} }

View file

@ -105,11 +105,11 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
// Add a special __test module to the crate that will contain code // Add a special __test module to the crate that will contain code
// generated for the test harness // generated for the test harness
let (mod_, reexport) = mk_test_module(&mut self.cx); let (mod_, reexport) = mk_test_module(&mut self.cx);
folded.module.items.push(mod_);
match reexport { match reexport {
Some(re) => folded.module.view_items.push(re), Some(re) => folded.module.items.push(re),
None => {} None => {}
} }
folded.module.items.push(mod_);
folded folded
} }
@ -205,22 +205,19 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
fn mk_reexport_mod(cx: &mut TestCtxt, tests: Vec<ast::Ident>, fn mk_reexport_mod(cx: &mut TestCtxt, tests: Vec<ast::Ident>,
tested_submods: Vec<(ast::Ident, ast::Ident)>) -> (P<ast::Item>, ast::Ident) { tested_submods: Vec<(ast::Ident, ast::Ident)>) -> (P<ast::Item>, ast::Ident) {
let mut view_items = Vec::new();
let super_ = token::str_to_ident("super"); let super_ = token::str_to_ident("super");
view_items.extend(tests.into_iter().map(|r| { let items = tests.into_iter().map(|r| {
cx.ext_cx.view_use_simple(DUMMY_SP, ast::Public, cx.ext_cx.item_use_simple(DUMMY_SP, ast::Public,
cx.ext_cx.path(DUMMY_SP, vec![super_, r])) cx.ext_cx.path(DUMMY_SP, vec![super_, r]))
})); }).chain(tested_submods.into_iter().map(|(r, sym)| {
view_items.extend(tested_submods.into_iter().map(|(r, sym)| {
let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]); let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]);
cx.ext_cx.view_use_simple_(DUMMY_SP, ast::Public, r, path) cx.ext_cx.item_use_simple_(DUMMY_SP, ast::Public, r, path)
})); }));
let reexport_mod = ast::Mod { let reexport_mod = ast::Mod {
inner: DUMMY_SP, inner: DUMMY_SP,
view_items: view_items, items: items.collect(),
items: Vec::new(),
}; };
let sym = token::gensym_ident("__test_reexports"); let sym = token::gensym_ident("__test_reexports");
@ -388,29 +385,29 @@ mod __test {
*/ */
fn mk_std(cx: &TestCtxt) -> ast::ViewItem { fn mk_std(cx: &TestCtxt) -> P<ast::Item> {
let id_test = token::str_to_ident("test"); let id_test = token::str_to_ident("test");
let (vi, vis) = if cx.is_test_crate { let (vi, vis, ident) = if cx.is_test_crate {
(ast::ViewItemUse( (ast::ItemUse(
P(nospan(ast::ViewPathSimple(id_test, P(nospan(ast::ViewPathSimple(id_test,
path_node(vec!(id_test)), path_node(vec!(id_test)))))),
ast::DUMMY_NODE_ID)))), ast::Public, token::special_idents::invalid)
ast::Public)
} else { } else {
(ast::ViewItemExternCrate(id_test, None, ast::DUMMY_NODE_ID), (ast::ItemExternCrate(None), ast::Inherited, id_test)
ast::Inherited)
}; };
ast::ViewItem { P(ast::Item {
id: ast::DUMMY_NODE_ID,
ident: ident,
node: vi, node: vi,
attrs: Vec::new(), attrs: vec![],
vis: vis, vis: vis,
span: DUMMY_SP span: DUMMY_SP
} })
} }
fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<ast::ViewItem>) { fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<P<ast::Item>>) {
// Link to test crate // Link to test crate
let view_items = vec!(mk_std(cx)); let import = mk_std(cx);
// A constant vector of test descriptors. // A constant vector of test descriptors.
let tests = mk_tests(cx); let tests = mk_tests(cx);
@ -427,8 +424,7 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<ast::ViewItem>) {
let testmod = ast::Mod { let testmod = ast::Mod {
inner: DUMMY_SP, inner: DUMMY_SP,
view_items: view_items, items: vec![import, mainfn, tests],
items: vec!(mainfn, tests),
}; };
let item_ = ast::ItemMod(testmod); let item_ = ast::ItemMod(testmod);
@ -439,34 +435,35 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<ast::ViewItem>) {
vec![unstable]))); vec![unstable])));
attr::mk_attr_inner(attr::mk_attr_id(), allow) attr::mk_attr_inner(attr::mk_attr_id(), allow)
}; };
let item = ast::Item { let item = P(ast::Item {
ident: mod_ident,
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
ident: mod_ident,
attrs: vec![allow_unstable],
node: item_, node: item_,
vis: ast::Public, vis: ast::Public,
span: DUMMY_SP, span: DUMMY_SP,
attrs: vec![allow_unstable], });
};
let reexport = cx.reexport_test_harness_main.as_ref().map(|s| { let reexport = cx.reexport_test_harness_main.as_ref().map(|s| {
// building `use <ident> = __test::main` // building `use <ident> = __test::main`
let reexport_ident = token::str_to_ident(s.get()); let reexport_ident = token::str_to_ident(s.get());
let use_path = let use_path =
nospan(ast::ViewPathSimple(reexport_ident, nospan(ast::ViewPathSimple(reexport_ident,
path_node(vec![mod_ident, token::str_to_ident("main")]), path_node(vec![mod_ident, token::str_to_ident("main")])));
ast::DUMMY_NODE_ID));
ast::ViewItem { P(ast::Item {
node: ast::ViewItemUse(P(use_path)), id: ast::DUMMY_NODE_ID,
ident: token::special_idents::invalid,
attrs: vec![], attrs: vec![],
node: ast::ItemUse(P(use_path)),
vis: ast::Inherited, vis: ast::Inherited,
span: DUMMY_SP span: DUMMY_SP
} })
}); });
debug!("Synthetic test module:\n{}\n", pprust::item_to_string(&item)); debug!("Synthetic test module:\n{}\n", pprust::item_to_string(&*item));
(P(item), reexport) (item, reexport)
} }
fn nospan<T>(t: T) -> codemap::Spanned<T> { fn nospan<T>(t: T) -> codemap::Spanned<T> {

View file

@ -69,13 +69,6 @@ pub fn string_to_stmt(source_str : String) -> P<ast::Stmt> {
}) })
} }
/// Parse a string, return a view item
pub fn string_to_view_item (source_str : String) -> ast::ViewItem {
with_error_checking_parse(source_str, |p| {
p.parse_view_item(Vec::new())
})
}
/// Parse a string, return a pat. Uses "irrefutable"... which doesn't /// Parse a string, return a pat. Uses "irrefutable"... which doesn't
/// (currently) affect parsing. /// (currently) affect parsing.
pub fn string_to_pat(source_str: String) -> P<ast::Pat> { pub fn string_to_pat(source_str: String) -> P<ast::Pat> {

View file

@ -62,7 +62,6 @@ pub trait Visitor<'v> : Sized {
self.visit_name(span, ident.name); self.visit_name(span, ident.name);
} }
fn visit_mod(&mut self, m: &'v Mod, _s: Span, _n: NodeId) { walk_mod(self, m) } fn visit_mod(&mut self, m: &'v Mod, _s: Span, _n: NodeId) { walk_mod(self, m) }
fn visit_view_item(&mut self, i: &'v ViewItem) { walk_view_item(self, i) }
fn visit_foreign_item(&mut self, i: &'v ForeignItem) { walk_foreign_item(self, i) } fn visit_foreign_item(&mut self, i: &'v ForeignItem) { walk_foreign_item(self, i) }
fn visit_item(&mut self, i: &'v Item) { walk_item(self, i) } fn visit_item(&mut self, i: &'v Item) { walk_item(self, i) }
fn visit_local(&mut self, l: &'v Local) { walk_local(self, l) } fn visit_local(&mut self, l: &'v Local) { walk_local(self, l) }
@ -166,51 +165,11 @@ pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
} }
pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) { pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) {
for view_item in module.view_items.iter() {
visitor.visit_view_item(view_item)
}
for item in module.items.iter() { for item in module.items.iter() {
visitor.visit_item(&**item) visitor.visit_item(&**item)
} }
} }
pub fn walk_view_item<'v, V: Visitor<'v>>(visitor: &mut V, vi: &'v ViewItem) {
match vi.node {
ViewItemExternCrate(name, _, _) => {
visitor.visit_ident(vi.span, name)
}
ViewItemUse(ref vp) => {
match vp.node {
ViewPathSimple(ident, ref path, id) => {
visitor.visit_ident(vp.span, ident);
visitor.visit_path(path, id);
}
ViewPathGlob(ref path, id) => {
visitor.visit_path(path, id);
}
ViewPathList(ref prefix, ref list, _) => {
for id in list.iter() {
match id.node {
PathListIdent { name, .. } => {
visitor.visit_ident(id.span, name);
}
PathListMod { .. } => ()
}
}
// Note that the `prefix` here is not a complete
// path, so we don't use `visit_path`.
walk_path(visitor, prefix);
}
}
}
}
for attr in vi.attrs.iter() {
visitor.visit_attribute(attr);
}
}
pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) { pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
visitor.visit_pat(&*local.pat); visitor.visit_pat(&*local.pat);
walk_ty_opt(visitor, &local.ty); walk_ty_opt(visitor, &local.ty);
@ -269,6 +228,32 @@ pub fn walk_trait_ref<'v,V>(visitor: &mut V,
pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
visitor.visit_ident(item.span, item.ident); visitor.visit_ident(item.span, item.ident);
match item.node { match item.node {
ItemExternCrate(..) => {}
ItemUse(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) => {
for id in list.iter() {
match id.node {
PathListIdent { name, .. } => {
visitor.visit_ident(id.span, name);
}
PathListMod { .. } => ()
}
}
// Note that the `prefix` here is not a complete
// path, so we don't use `visit_path`.
walk_path(visitor, prefix);
}
}
}
ItemStatic(ref typ, _, ref expr) | ItemStatic(ref typ, _, ref expr) |
ItemConst(ref typ, ref expr) => { ItemConst(ref typ, ref expr) => {
visitor.visit_ty(&**typ); visitor.visit_ty(&**typ);
@ -285,9 +270,6 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
visitor.visit_mod(module, item.span, item.id) visitor.visit_mod(module, item.span, item.id)
} }
ItemForeignMod(ref foreign_module) => { ItemForeignMod(ref foreign_module) => {
for view_item in foreign_module.view_items.iter() {
visitor.visit_view_item(view_item)
}
for foreign_item in foreign_module.items.iter() { for foreign_item in foreign_module.items.iter() {
visitor.visit_foreign_item(&**foreign_item) visitor.visit_foreign_item(&**foreign_item)
} }
@ -732,9 +714,6 @@ pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V,
} }
pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) { pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) {
for view_item in block.view_items.iter() {
visitor.visit_view_item(view_item)
}
for statement in block.stmts.iter() { for statement in block.stmts.iter() {
visitor.visit_stmt(&**statement) visitor.visit_stmt(&**statement)
} }

View file

@ -1,4 +1,4 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // Copyright 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.
// //
@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
pub extern crate core; //~ ERROR: `pub` visibility is not allowed #![crate_type="lib"]
fn main() { pub const X: () = ();
pub use std::usize; //~ ERROR: imports in functions are never reachable
}

View file

@ -0,0 +1,13 @@
// 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_type="lib"]
pub const Y: () = ();

View file

@ -11,8 +11,7 @@
// aux-build:macro_crate_test.rs // aux-build:macro_crate_test.rs
// ignore-stage1 // ignore-stage1
#[plugin] #[no_link] #[plugin] #[no_link] extern crate macro_crate_test;
//~^ ERROR compiler plugins are experimental and possibly buggy //~^ ERROR compiler plugins are experimental and possibly buggy
extern crate macro_crate_test;
fn main() {} fn main() {}

View file

@ -0,0 +1,20 @@
// 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.
mod foo { pub struct Bar; }
fn main() {
{
struct Bar;
use foo::Bar;
//~^ ERROR import `Bar` conflicts with type in this module
//~^^ ERROR import `Bar` conflicts with value in this module
}
}

View file

@ -0,0 +1,18 @@
// 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.
mod foo { struct bar; }
fn main() {
let bar = 5;
//~^ ERROR declaration of `bar` shadows an enum variant or unit-like struct in scope
use foo::bar;
//~^ ERROR imports are not allowed after non-item statements
}

View file

@ -1,4 +1,4 @@
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // Copyright 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.
// //
@ -8,12 +8,8 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
extern crate test; mod foo { pub mod foo { } }
fn f() { use foo::foo; //~ ERROR import `foo` conflicts with existing submodule
}
use test::net; //~ ERROR `use` and `extern crate` declarations must precede items fn main() {}
fn main() {
}

View file

@ -0,0 +1,20 @@
// 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.
mod bar {
pub fn foo() -> bool { true }
}
fn main() {
let foo = |&:| false;
use bar::foo;
//~^ ERROR imports are not allowed after non-item statements
assert_eq!(foo(), false);
}

View file

@ -1,4 +1,4 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // Copyright 2013-2014 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.
// //
@ -9,6 +9,7 @@
// except according to those terms. // except according to those terms.
fn main() { fn main() {
pub use std::uint; //~ ERROR: visibility has no effect
pub struct A; //~ ERROR: visibility has no effect pub struct A; //~ ERROR: visibility has no effect
pub enum B {} //~ ERROR: visibility has no effect pub enum B {} //~ ERROR: visibility has no effect
pub trait C { //~ ERROR: visibility has no effect pub trait C { //~ ERROR: visibility has no effect

View file

@ -1,8 +1,8 @@
#![no_std] #![no_std]
#[macro_use]
extern crate "std" as std;
#[prelude_import] #[prelude_import]
use std::prelude::v1::*; use std::prelude::v1::*;
#[macro_use]
extern crate "std" as std;
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // Copyright 2014 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.

View file

@ -0,0 +1,33 @@
// 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.
// aux-build:blind-item-mixed-crate-use-item-foo.rs
// aux-build:blind-item-mixed-crate-use-item-foo2.rs
mod m {
pub fn f<T>(_: T, _: (), _: ()) { }
pub fn g<T>(_: T, _: (), _: ()) { }
}
const BAR: () = ();
struct Data;
use m::f;
extern crate "blind-item-mixed-crate-use-item-foo" as foo;
fn main() {
const BAR2: () = ();
struct Data2;
use m::g;
extern crate "blind-item-mixed-crate-use-item-foo2" as foo2;
f(Data, BAR, foo::X);
g(Data2, BAR2, foo2::Y);
}

View file

@ -0,0 +1,27 @@
// 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.
mod m {
pub fn f<T>(_: T, _: ()) { }
pub fn g<T>(_: T, _: ()) { }
}
const BAR: () = ();
struct Data;
use m::f;
fn main() {
const BAR2: () = ();
struct Data2;
use m::g;
f(Data, BAR);
g(Data2, BAR2);
}