about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNilstrieb <48135649+Nilstrieb@users.noreply.github.com>2024-05-01 17:37:22 +0200
committerNilstrieb <48135649+Nilstrieb@users.noreply.github.com>2024-05-04 14:48:42 +0200
commit1572c0dcd7b5d9e4fcd400d3b34f1d675201f150 (patch)
treefe2164aedfdc2d4709d0e9ffdd849374f8612d7d
parent6d721dd0b80ad5382d38481a2477f7404b73e717 (diff)
downloadrust-1572c0dcd7b5d9e4fcd400d3b34f1d675201f150.tar.gz
rust-1572c0dcd7b5d9e4fcd400d3b34f1d675201f150.zip
Various improvements to entrypoint code
This moves some code around and adds some documentation comments to make
it easier to understand what's going on with the entrypoint logic, which
is a bit complicated.

The only change in behavior is consolidating the error messages for
unix_sigpipe to make the code slightly simpler.
-rw-r--r--compiler/rustc_ast/src/entry.rs26
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs2
-rw-r--r--compiler/rustc_passes/messages.ftl6
-rw-r--r--compiler/rustc_passes/src/entry.rs42
-rw-r--r--compiler/rustc_passes/src/errors.rs16
5 files changed, 49 insertions, 43 deletions
diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs
index cd8a5a66920..dd231e286d5 100644
--- a/compiler/rustc_ast/src/entry.rs
+++ b/compiler/rustc_ast/src/entry.rs
@@ -4,11 +4,35 @@ use rustc_span::Symbol;
 
 #[derive(Debug)]
 pub enum EntryPointType {
+    /// This function is not an entrypoint.
     None,
+    /// This is a function called `main` at the root level.
+    /// ```
+    /// fn main() {}
+    /// ```
     MainNamed,
+    /// This is a function with the `#[rustc_main]` attribute.
+    /// Used by the testing harness to create the test entrypoint.
+    /// ```ignore (clashes with test entrypoint)
+    /// #[rustc_main]
+    /// fn main() {}
+    /// ```
     RustcMainAttr,
+    /// This is a function with the `#[start]` attribute.
+    /// ```ignore (clashes with test entrypoint)
+    /// #[start]
+    /// fn main() {}
+    /// ```
     Start,
-    OtherMain, // Not an entry point, but some other function named main
+    /// This function is **not** an entrypoint but simply named `main` (not at the root).
+    /// This is only used for diagnostics.
+    /// ```
+    /// #[allow(dead_code)]
+    /// mod meow {
+    ///     fn main() {}
+    /// }
+    /// ```
+    OtherMain,
 }
 
 pub fn entry_point_type(
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index a2015445b42..8cf431482ff 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -266,7 +266,7 @@ fn generate_test_harness(
 ///
 /// By default this expands to
 ///
-/// ```ignore UNSOLVED (I think I still need guidance for this one. Is it correct? Do we try to make it run? How do we nicely fill it out?)
+/// ```ignore (messes with test internals)
 /// #[rustc_main]
 /// pub fn main() {
 ///     extern crate test;
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 8878310d6e9..9d58d301e2b 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -49,12 +49,6 @@ passes_attr_crate_level =
 passes_attr_only_in_functions =
     `{$attr}` attribute can only be used on functions
 
-passes_attr_only_on_main =
-    `{$attr}` attribute can only be used on `fn main()`
-
-passes_attr_only_on_root_main =
-    `{$attr}` attribute can only be used on root `fn main()`
-
 passes_both_ffi_const_and_pure =
     `#[ffi_const]` function cannot be `#[ffi_pure]`
 
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index d52092f2aa9..b43c8282db1 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -18,10 +18,10 @@ use crate::errors::{
 struct EntryContext<'tcx> {
     tcx: TyCtxt<'tcx>,
 
-    /// The function that has attribute named `main`.
-    attr_main_fn: Option<(LocalDefId, Span)>,
+    /// The function has the `#[rustc_main]` attribute.
+    rustc_main_fn: Option<(LocalDefId, Span)>,
 
-    /// The function that has the attribute 'start' on it.
+    /// The function that has the attribute `#[start]` on it.
     start_fn: Option<(LocalDefId, Span)>,
 
     /// The functions that one might think are `main` but aren't, e.g.
@@ -42,10 +42,10 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
     }
 
     let mut ctxt =
-        EntryContext { tcx, attr_main_fn: None, start_fn: None, non_main_fns: Vec::new() };
+        EntryContext { tcx, rustc_main_fn: None, start_fn: None, non_main_fns: Vec::new() };
 
     for id in tcx.hir().items() {
-        find_item(id, &mut ctxt);
+        check_and_search_item(id, &mut ctxt);
     }
 
     configure_main(tcx, &ctxt)
@@ -56,7 +56,16 @@ fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Opti
     attr::find_by_name(attrs, sym).map(|attr| attr.span)
 }
 
-fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
+fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
+    if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) {
+        for attr in [sym::start, sym::rustc_main] {
+            if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
+                ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr });
+            }
+        }
+        return;
+    }
+
     let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID);
 
     let attrs = ctxt.tcx.hir().attrs(id.hir_id());
@@ -65,26 +74,20 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
         at_root,
         ctxt.tcx.opt_item_name(id.owner_id.to_def_id()),
     );
+
     match entry_point_type {
-        EntryPointType::None => (),
-        _ if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) => {
-            for attr in [sym::start, sym::rustc_main] {
-                if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
-                    ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr });
-                }
-            }
-        }
-        EntryPointType::MainNamed => (),
+        EntryPointType::None => {}
+        EntryPointType::MainNamed => {}
         EntryPointType::OtherMain => {
             ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id));
         }
         EntryPointType::RustcMainAttr => {
-            if ctxt.attr_main_fn.is_none() {
-                ctxt.attr_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
+            if ctxt.rustc_main_fn.is_none() {
+                ctxt.rustc_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
             } else {
                 ctxt.tcx.dcx().emit_err(MultipleRustcMain {
                     span: ctxt.tcx.def_span(id.owner_id.to_def_id()),
-                    first: ctxt.attr_main_fn.unwrap().1,
+                    first: ctxt.rustc_main_fn.unwrap().1,
                     additional: ctxt.tcx.def_span(id.owner_id.to_def_id()),
                 });
             }
@@ -107,10 +110,11 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
 fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> {
     if let Some((def_id, _)) = visitor.start_fn {
         Some((def_id.to_def_id(), EntryFnType::Start))
-    } else if let Some((local_def_id, _)) = visitor.attr_main_fn {
+    } else if let Some((local_def_id, _)) = visitor.rustc_main_fn {
         let def_id = local_def_id.to_def_id();
         Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) }))
     } else {
+        // The actual resolution of main happens in the resolver, this here
         if let Some(main_def) = tcx.resolutions(()).main_def
             && let Some(def_id) = main_def.opt_fn_def_id()
         {
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 743faf54560..65cad82cc8c 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1207,22 +1207,6 @@ pub struct NakedFunctionsMustUseNoreturn {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_attr_only_on_main)]
-pub struct AttrOnlyOnMain {
-    #[primary_span]
-    pub span: Span,
-    pub attr: Symbol,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_attr_only_on_root_main)]
-pub struct AttrOnlyOnRootMain {
-    #[primary_span]
-    pub span: Span,
-    pub attr: Symbol,
-}
-
-#[derive(Diagnostic)]
 #[diag(passes_attr_only_in_functions)]
 pub struct AttrOnlyInFunctions {
     #[primary_span]