Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Turn extern crate and use into first-class items. #20179

Merged
merged 15 commits into from
Jan 22, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 9 additions & 23 deletions src/doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -803,8 +803,9 @@ Crates contain [items](#items), each of which may have some number of
## Items

```{.ebnf .gram}
item : mod_item | fn_item | type_item | struct_item | enum_item
| static_item | trait_item | impl_item | extern_block ;
item : extern_crate_decl | use_decl | mod_item | fn_item | type_item
| 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
Expand All @@ -818,6 +819,8 @@ execution, and may reside in read-only memory.

There are several kinds of item:

* [`extern crate` declarations](#extern-crate-declarations)
* [`use` declarations](#use-declarations)
* [modules](#modules)
* [functions](#functions)
* [type definitions](#type-definitions)
Expand Down Expand Up @@ -854,13 +857,10 @@ no notion of type abstraction: there are no first-class "forall" types.

```{.ebnf .gram}
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
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 is a container for zero or more [items](#items).

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
Expand Down Expand Up @@ -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

```{.ebnf .gram}
Expand Down Expand Up @@ -2891,13 +2878,12 @@ Point3d {y: 0, z: 10, .. base};
### Block expressions

```{.ebnf .gram}
block_expr : '{' [ view_item ] *
[ stmt ';' | item ] *
block_expr : '{' [ stmt ';' | item ] *
[ expr ] '}' ;
```

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
the block itself.

Expand Down
1 change: 1 addition & 0 deletions src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ register_diagnostics! {
E0140,
E0152,
E0153,
E0154,
E0157,
E0158,
E0161,
Expand Down
37 changes: 16 additions & 21 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1202,17 +1202,17 @@ impl LintPass for UnusedImportBraces {
lint_array!(UNUSED_IMPORT_BRACES)
}

fn check_view_item(&mut self, cx: &Context, view_item: &ast::ViewItem) {
match view_item.node {
ast::ViewItemUse(ref view_path) => {
fn check_item(&mut self, cx: &Context, item: &ast::Item) {
match item.node {
ast::ItemUse(ref view_path) => {
match view_path.node {
ast::ViewPathList(_, ref items, _) => {
ast::ViewPathList(_, ref items) => {
if items.len() == 1 {
match items[0].node {
ast::PathListIdent {ref name, ..} => {
let m = format!("braces around {} is unnecessary",
token::get_ident(*name).get());
cx.span_lint(UNUSED_IMPORT_BRACES, view_item.span,
cx.span_lint(UNUSED_IMPORT_BRACES, item.span,
&m[]);
},
_ => ()
Expand Down Expand Up @@ -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) {
if self.is_internal(cx, e.span) { return; }

Expand Down Expand Up @@ -1776,6 +1760,17 @@ impl LintPass for Stability {
if self.is_internal(cx, item.span) { return }

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, _) => {
for t in supertraits.iter() {
if let ast::TraitTyParamBound(ref t, _) = *t {
Expand Down
8 changes: 0 additions & 8 deletions src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,14 +603,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) {
run_lints!(self, check_pat, p);
visit::walk_pat(self, p);
Expand Down
1 change: 0 additions & 1 deletion src/librustc/lint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ pub trait LintPass {
fn check_crate(&mut self, _: &Context, _: &ast::Crate) { }
fn check_ident(&mut self, _: &Context, _: Span, _: ast::Ident) { }
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_item(&mut self, _: &Context, _: &ast::Item) { }
fn check_local(&mut self, _: &Context, _: &ast::Local) { }
Expand Down
56 changes: 25 additions & 31 deletions src/librustc/metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ pub struct 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) {
self.process_item(a);
visit::walk_item(self, a);
Expand All @@ -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")

}

struct CrateInfo {
Expand Down Expand Up @@ -181,29 +176,10 @@ impl<'a> CrateReader<'a> {
}
}

fn process_view_item(&mut self, i: &ast::ViewItem) {
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> {
fn extract_crate_info(&self, i: &ast::Item) -> Option<CrateInfo> {
match i.node {
ast::ViewItemExternCrate(ident, ref path_opt, id) => {
let ident = token::get_ident(ident);
ast::ItemExternCrate(ref path_opt) => {
let ident = token::get_ident(i.ident);
debug!("resolving extern crate stmt. ident: {} path_opt: {:?}",
ident, path_opt);
let name = match *path_opt {
Expand All @@ -218,16 +194,34 @@ impl<'a> CrateReader<'a> {
Some(CrateInfo {
ident: ident.get().to_string(),
name: name,
id: id,
id: i.id,
should_link: should_link(i),
})
}
_ => None
}
}

fn process_item(&self, i: &ast::Item) {
fn process_item(&mut self, i: &ast::Item) {
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) => {
if fm.abi == abi::Rust || fm.abi == abi::RustIntrinsic {
return;
Expand Down Expand Up @@ -533,7 +527,7 @@ impl<'a> CrateReader<'a> {

#[derive(Copy)]
pub enum CrateOrString<'a> {
Krate(&'a ast::ViewItem),
Krate(&'a ast::Item),
Str(&'a str)
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1456,8 +1456,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
rbml_w.end_tag();
}
}
ast::ItemMac(..) => {
// macros are encoded separately
ast::ItemExternCrate(_) | ast::ItemUse(_) |ast::ItemMac(..) => {
// these are encoded separately
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,8 +332,6 @@ impl Folder for NestedItemsDropper {
}
}).collect();
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,
expr: expr,
id: id,
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/reachable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
// These are normal, nothing reachable about these
// inherently and their children are already in the
// worklist, as determined by the privacy pass
ast::ItemExternCrate(_) | ast::ItemUse(_) |
ast::ItemTy(..) | ast::ItemStatic(_, _, _) |
ast::ItemMod(..) | ast::ItemForeignMod(..) |
ast::ItemImpl(..) | ast::ItemTrait(..) |
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
// Fn lifetimes get added in visit_fn below:
visit::walk_item(this, item);
}
ast::ItemExternCrate(_) |
ast::ItemUse(_) |
ast::ItemMod(..) |
ast::ItemMac(..) |
ast::ItemForeignMod(..) |
Expand Down
24 changes: 16 additions & 8 deletions src/librustc/plugin/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
// crate root, because `$crate` won't work properly. Identify these by
// spans, because the crate map isn't set up yet.
for vi in krate.module.view_items.iter() {
loader.span_whitelist.insert(vi.span);
for item in krate.module.items.iter() {
if let ast::ItemExternCrate(_) = item.node {
loader.span_whitelist.insert(item.span);
}
}

visit::walk_crate(&mut loader, krate);
Expand All @@ -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.
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`.
match vi.node {
ast::ViewItemExternCrate(..) => (),
_ => return,
match item.node {
ast::ItemExternCrate(_) => {}
_ => {
visit::walk_item(self, item);
return;
}
}

// Parse the attributes relating to macro / plugin loading.
let mut plugin_attr = None;
let mut macro_selection = Some(HashSet::new()); // None => load all
let mut reexport = HashSet::new();
for attr in vi.attrs.iter() {
for attr in item.attrs.iter() {
let mut used = true;
match attr.name().get() {
"phase" => {
Expand Down Expand Up @@ -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) {
Expand Down
14 changes: 0 additions & 14 deletions src/librustc_back/svh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,6 @@ mod svh_visitor {
SawLifetimeDef(token::InternedString),

SawMod,
SawViewItem,
SawForeignItem,
SawItem,
SawDecl,
Expand Down Expand Up @@ -436,19 +435,6 @@ mod svh_visitor {
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) {
// FIXME (#14132) ideally we would incorporate privacy (or
// perhaps reachability) somewhere here, so foreign items
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_driver/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ impl fold::Folder for ReplaceBodyWithLoop {
e: Option<P<ast::Expr>>) -> P<ast::Block> {
P(ast::Block {
expr: e,
view_items: vec![], stmts: vec![], rules: rules,
stmts: vec![], rules: rules,
id: ast::DUMMY_NODE_ID, span: codemap::DUMMY_SP,
})
}
Expand Down
Loading