about summary refs log tree commit diff
path: root/compiler/rustc_passes/src
diff options
context:
space:
mode:
authorCharles Lew <crlf0710@gmail.com>2021-04-26 01:09:35 +0800
committerCharles Lew <crlf0710@gmail.com>2021-04-29 08:35:08 +0800
commitd261df4a72e60e8baa0f21b67eba8f7b91cc2135 (patch)
tree4547e05f08c17033fdc8da3d03415010f213d82c /compiler/rustc_passes/src
parent727d101561f9b1e81c6282943292d990288ca479 (diff)
downloadrust-d261df4a72e60e8baa0f21b67eba8f7b91cc2135.tar.gz
rust-d261df4a72e60e8baa0f21b67eba8f7b91cc2135.zip
Implement RFC 1260 with feature_name `imported_main`.
Diffstat (limited to 'compiler/rustc_passes/src')
-rw-r--r--compiler/rustc_passes/src/dead.rs4
-rw-r--r--compiler/rustc_passes/src/entry.rs51
2 files changed, 31 insertions, 24 deletions
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index c63edf365a1..d32180525bf 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -472,7 +472,9 @@ fn create_and_seed_worklist<'tcx>(
         )
         .chain(
             // Seed entry point
-            tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().local_def_id_to_hir_id(def_id)),
+            tcx.entry_fn(LOCAL_CRATE).and_then(|(def_id, _)| {
+                def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
+            }),
         )
         .collect::<Vec<_>>();
 
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index e1b750df33c..65cfe986ad4 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -1,12 +1,13 @@
 use rustc_ast::entry::EntryPointType;
 use rustc_errors::struct_span_err;
-use rustc_hir::def_id::{CrateNum, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{ForeignItem, HirId, ImplItem, Item, ItemKind, TraitItem, CRATE_HIR_ID};
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{CrateType, EntryFnType};
+use rustc_session::parse::feature_err;
 use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, DUMMY_SP};
@@ -16,9 +17,6 @@ struct EntryContext<'a, 'tcx> {
 
     map: Map<'tcx>,
 
-    /// The top-level function called `main`.
-    main_fn: Option<(HirId, Span)>,
-
     /// The function that has attribute named `main`.
     attr_main_fn: Option<(HirId, Span)>,
 
@@ -50,7 +48,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
     }
 }
 
-fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(LocalDefId, EntryFnType)> {
+fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> {
     assert_eq!(cnum, LOCAL_CRATE);
 
     let any_exe = tcx.sess.crate_types().iter().any(|ty| *ty == CrateType::Executable);
@@ -67,7 +65,6 @@ fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(LocalDefId, EntryFnType)
     let mut ctxt = EntryContext {
         session: tcx.sess,
         map: tcx.hir(),
-        main_fn: None,
         attr_main_fn: None,
         start_fn: None,
         non_main_fns: Vec::new(),
@@ -115,14 +112,7 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
                 throw_attr_err(&ctxt.session, attr.span, "rustc_main");
             }
         }
-        EntryPointType::MainNamed => {
-            if ctxt.main_fn.is_none() {
-                ctxt.main_fn = Some((item.hir_id(), item.span));
-            } else {
-                struct_span_err!(ctxt.session, item.span, E0136, "multiple `main` functions")
-                    .emit();
-            }
-        }
+        EntryPointType::MainNamed => (),
         EntryPointType::OtherMain => {
             ctxt.non_main_fns.push((item.hir_id(), item.span));
         }
@@ -154,16 +144,23 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
     }
 }
 
-fn configure_main(
-    tcx: TyCtxt<'_>,
-    visitor: &EntryContext<'_, '_>,
-) -> Option<(LocalDefId, EntryFnType)> {
+fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(DefId, EntryFnType)> {
     if let Some((hir_id, _)) = visitor.start_fn {
-        Some((tcx.hir().local_def_id(hir_id), EntryFnType::Start))
+        Some((tcx.hir().local_def_id(hir_id).to_def_id(), EntryFnType::Start))
     } else if let Some((hir_id, _)) = visitor.attr_main_fn {
-        Some((tcx.hir().local_def_id(hir_id), EntryFnType::Main))
-    } else if let Some((hir_id, _)) = visitor.main_fn {
-        Some((tcx.hir().local_def_id(hir_id), EntryFnType::Main))
+        Some((tcx.hir().local_def_id(hir_id).to_def_id(), EntryFnType::Main))
+    } else if let Some(def_id) = tcx.main_def.and_then(|main_def| main_def.opt_fn_def_id()) {
+        if tcx.main_def.unwrap().is_import && !tcx.features().imported_main {
+            let span = tcx.main_def.unwrap().span;
+            feature_err(
+                &tcx.sess.parse_sess,
+                sym::imported_main,
+                span,
+                "using an imported function as entry point `main` is experimental",
+            )
+            .emit();
+        }
+        Some((def_id, EntryFnType::Main))
     } else {
         no_main_err(tcx, visitor);
         None
@@ -213,6 +210,14 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
     } else {
         err.note(&note);
     }
+
+    if let Some(main_def) = tcx.main_def {
+        if main_def.opt_fn_def_id().is_none() {
+            // There is something at `crate::main`, but it is not a function definition.
+            err.span_label(main_def.span, &format!("non-function item at `crate::main` is found"));
+        }
+    }
+
     if tcx.sess.teach(&err.get_code().unwrap()) {
         err.note(
             "If you don't know the basics of Rust, you can go look to the Rust Book \
@@ -222,7 +227,7 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
     err.emit();
 }
 
-pub fn find_entry_point(tcx: TyCtxt<'_>) -> Option<(LocalDefId, EntryFnType)> {
+pub fn find_entry_point(tcx: TyCtxt<'_>) -> Option<(DefId, EntryFnType)> {
     tcx.entry_fn(LOCAL_CRATE)
 }