]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/middle/entry.rs
Rollup merge of #31054 - steveklabnik:a11y, r=alexcrichton
[rust.git] / src / librustc / middle / entry.rs
index 4b45aedd47640c9dfb69026e5a6572b0af792966..2d096f66e09f6798e5e9358410bc36322c4fbdbc 100644 (file)
 
 
 use front::map as ast_map;
+use middle::def_id::{CRATE_DEF_INDEX};
 use session::{config, Session};
 use syntax::ast::NodeId;
 use syntax::attr;
 use syntax::codemap::Span;
 use syntax::entry::EntryPointType;
 use rustc_front::hir::{Item, ItemFn};
-use rustc_front::visit;
-use rustc_front::visit::Visitor;
+use rustc_front::intravisit::Visitor;
 
-struct EntryContext<'a> {
+struct EntryContext<'a, 'tcx: 'a> {
     session: &'a Session,
 
-    // The current depth in the ast
-    depth: usize,
+    map: &'a ast_map::Map<'tcx>,
 
     // The top-level function called 'main'
     main_fn: Option<(NodeId, Span)>,
@@ -39,11 +38,12 @@ struct EntryContext<'a> {
     non_main_fns: Vec<(NodeId, Span)> ,
 }
 
-impl<'a, 'v> Visitor<'v> for EntryContext<'a> {
-    fn visit_item(&mut self, item: &Item) {
-        self.depth += 1;
-        find_item(item, self);
-        self.depth -= 1;
+impl<'a, 'tcx> Visitor<'tcx> for EntryContext<'a, 'tcx> {
+    fn visit_item(&mut self, item: &'tcx Item) {
+        let def_id = self.map.local_def_id(item.id);
+        let def_key = self.map.def_key(def_id);
+        let at_root = def_key.parent == Some(CRATE_DEF_INDEX);
+        find_item(item, self, at_root);
     }
 }
 
@@ -64,29 +64,29 @@ pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map) {
 
     let mut ctxt = EntryContext {
         session: session,
-        depth: 0,
+        map: ast_map,
         main_fn: None,
         attr_main_fn: None,
         start_fn: None,
         non_main_fns: Vec::new(),
     };
 
-    visit::walk_crate(&mut ctxt, ast_map.krate());
+    ast_map.krate().visit_all_items(&mut ctxt);
 
     configure_main(&mut ctxt);
 }
 
 // Beware, this is duplicated in libsyntax/entry.rs, make sure to keep
 // them in sync.
-fn entry_point_type(item: &Item, depth: usize) -> EntryPointType {
+fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType {
     match item.node {
         ItemFn(..) => {
             if attr::contains_name(&item.attrs, "start") {
                 EntryPointType::Start
             } else if attr::contains_name(&item.attrs, "main") {
                 EntryPointType::MainAttr
-            } else if item.name == "main" {
-                if depth == 1 {
+            } else if item.name.as_str() == "main" {
+                if at_root {
                     // This is a top-level function so can be 'main'
                     EntryPointType::MainNamed
                 } else {
@@ -101,8 +101,8 @@ fn entry_point_type(item: &Item, depth: usize) -> EntryPointType {
 }
 
 
-fn find_item(item: &Item, ctxt: &mut EntryContext) {
-    match entry_point_type(item, ctxt.depth) {
+fn find_item(item: &Item, ctxt: &mut EntryContext, at_root: bool) {
+    match entry_point_type(item, at_root) {
         EntryPointType::MainNamed => {
             if ctxt.main_fn.is_none() {
                 ctxt.main_fn = Some((item.id, item.span));
@@ -132,8 +132,6 @@ fn find_item(item: &Item, ctxt: &mut EntryContext) {
         },
         EntryPointType::None => ()
     }
-
-    visit::walk_item(ctxt, item);
 }
 
 fn configure_main(this: &mut EntryContext) {
@@ -148,17 +146,20 @@ fn configure_main(this: &mut EntryContext) {
         this.session.entry_type.set(Some(config::EntryMain));
     } else {
         // No main function
-        this.session.err("main function not found");
+        let mut err = this.session.struct_err("main function not found");
         if !this.non_main_fns.is_empty() {
             // There were some functions named 'main' though. Try to give the user a hint.
-            this.session.note("the main function must be defined at the crate level \
-                               but you have one or more functions named 'main' that are not \
-                               defined at the crate level. Either move the definition or \
-                               attach the `#[main]` attribute to override this behavior.");
+            err.note("the main function must be defined at the crate level \
+                      but you have one or more functions named 'main' that are not \
+                      defined at the crate level. Either move the definition or \
+                      attach the `#[main]` attribute to override this behavior.");
             for &(_, span) in &this.non_main_fns {
-                this.session.span_note(span, "here is a function named 'main'");
+                err.span_note(span, "here is a function named 'main'");
             }
+            err.emit();
             this.session.abort_if_errors();
+        } else {
+            err.emit();
         }
     }
 }