Skip to content

Commit 2fc12e4

Browse files
committed
Auto merge of rust-lang#124584 - Nilstrieb:entrypointy, r=fee1-dead
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.
2 parents cfb2410 + dfa695f commit 2fc12e4

13 files changed

+66
-53
lines changed

Diff for: compiler/rustc_ast/src/entry.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,34 @@ use rustc_span::Symbol;
44

55
#[derive(Debug)]
66
pub enum EntryPointType {
7+
/// This function is not an entrypoint.
78
None,
9+
/// This is a function called `main` at the root level.
10+
/// ```
11+
/// fn main() {}
12+
/// ```
813
MainNamed,
14+
/// This is a function with the `#[rustc_main]` attribute.
15+
/// Used by the testing harness to create the test entrypoint.
16+
/// ```ignore (clashes with test entrypoint)
17+
/// #[rustc_main]
18+
/// fn main() {}
19+
/// ```
920
RustcMainAttr,
21+
/// This is a function with the `#[start]` attribute.
22+
/// ```ignore (clashes with test entrypoint)
23+
/// #[start]
24+
/// fn main() {}
25+
/// ```
1026
Start,
11-
OtherMain, // Not an entry point, but some other function named main
27+
/// This function is **not** an entrypoint but simply named `main` (not at the root).
28+
/// This is only used for diagnostics.
29+
/// ```
30+
/// mod meow {
31+
/// fn main() {}
32+
/// }
33+
/// ```
34+
OtherMain,
1235
}
1336

1437
pub fn entry_point_type(

Diff for: compiler/rustc_builtin_macros/src/test_harness.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ fn generate_test_harness(
266266
///
267267
/// By default this expands to
268268
///
269-
/// ```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?)
269+
/// ```ignore (messes with test internals)
270270
/// #[rustc_main]
271271
/// pub fn main() {
272272
/// extern crate test;

Diff for: compiler/rustc_passes/messages.ftl

+1-4
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,7 @@ passes_attr_only_in_functions =
5050
`{$attr}` attribute can only be used on functions
5151
5252
passes_attr_only_on_main =
53-
`{$attr}` attribute can only be used on `fn main()`
54-
55-
passes_attr_only_on_root_main =
56-
`{$attr}` attribute can only be used on root `fn main()`
53+
`{$attr}` attribute can only be used on the root `fn main()`
5754
5855
passes_both_ffi_const_and_pure =
5956
`#[ffi_const]` function cannot be `#[ffi_pure]`

Diff for: compiler/rustc_passes/src/entry.rs

+32-31
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@ use rustc_span::symbol::sym;
1212
use rustc_span::{Span, Symbol};
1313

1414
use crate::errors::{
15-
AttrOnlyInFunctions, AttrOnlyOnMain, AttrOnlyOnRootMain, ExternMain, MultipleRustcMain,
16-
MultipleStartFunctions, NoMainErr, UnixSigpipeValues,
15+
AttrOnlyInFunctions, AttrOnlyOnMain, ExternMain, MultipleRustcMain, MultipleStartFunctions,
16+
NoMainErr, UnixSigpipeValues,
1717
};
1818

1919
struct EntryContext<'tcx> {
2020
tcx: TyCtxt<'tcx>,
2121

22-
/// The function that has attribute named `main`.
23-
attr_main_fn: Option<(LocalDefId, Span)>,
22+
/// The function has the `#[rustc_main]` attribute.
23+
rustc_main_fn: Option<(LocalDefId, Span)>,
2424

25-
/// The function that has the attribute 'start' on it.
25+
/// The function that has the attribute `#[start]` on it.
2626
start_fn: Option<(LocalDefId, Span)>,
2727

2828
/// The functions that one might think are `main` but aren't, e.g.
@@ -43,10 +43,10 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
4343
}
4444

4545
let mut ctxt =
46-
EntryContext { tcx, attr_main_fn: None, start_fn: None, non_main_fns: Vec::new() };
46+
EntryContext { tcx, rustc_main_fn: None, start_fn: None, non_main_fns: Vec::new() };
4747

4848
for id in tcx.hir().items() {
49-
find_item(id, &mut ctxt);
49+
check_and_search_item(id, &mut ctxt);
5050
}
5151

5252
configure_main(tcx, &ctxt)
@@ -57,7 +57,16 @@ fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Opti
5757
attr::find_by_name(attrs, sym).map(|attr| attr.span)
5858
}
5959

60-
fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
60+
fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
61+
if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) {
62+
for attr in [sym::start, sym::rustc_main] {
63+
if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
64+
ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr });
65+
}
66+
}
67+
return;
68+
}
69+
6170
let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID);
6271

6372
let attrs = ctxt.tcx.hir().attrs(id.hir_id());
@@ -66,41 +75,32 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
6675
at_root,
6776
ctxt.tcx.opt_item_name(id.owner_id.to_def_id()),
6877
);
78+
79+
if let EntryPointType::None | EntryPointType::OtherMain | EntryPointType::Start =
80+
entry_point_type
81+
&& let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe)
82+
{
83+
ctxt.tcx.dcx().emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe });
84+
}
85+
6986
match entry_point_type {
70-
EntryPointType::None => {
71-
if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
72-
ctxt.tcx.dcx().emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe });
73-
}
74-
}
75-
_ if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) => {
76-
for attr in [sym::start, sym::rustc_main] {
77-
if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
78-
ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr });
79-
}
80-
}
81-
}
82-
EntryPointType::MainNamed => (),
87+
EntryPointType::None => {}
88+
EntryPointType::MainNamed => {}
8389
EntryPointType::OtherMain => {
84-
if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
85-
ctxt.tcx.dcx().emit_err(AttrOnlyOnRootMain { span, attr: sym::unix_sigpipe });
86-
}
8790
ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id));
8891
}
8992
EntryPointType::RustcMainAttr => {
90-
if ctxt.attr_main_fn.is_none() {
91-
ctxt.attr_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
93+
if ctxt.rustc_main_fn.is_none() {
94+
ctxt.rustc_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
9295
} else {
9396
ctxt.tcx.dcx().emit_err(MultipleRustcMain {
9497
span: ctxt.tcx.def_span(id.owner_id.to_def_id()),
95-
first: ctxt.attr_main_fn.unwrap().1,
98+
first: ctxt.rustc_main_fn.unwrap().1,
9699
additional: ctxt.tcx.def_span(id.owner_id.to_def_id()),
97100
});
98101
}
99102
}
100103
EntryPointType::Start => {
101-
if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
102-
ctxt.tcx.dcx().emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe });
103-
}
104104
if ctxt.start_fn.is_none() {
105105
ctxt.start_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
106106
} else {
@@ -118,10 +118,11 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
118118
fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> {
119119
if let Some((def_id, _)) = visitor.start_fn {
120120
Some((def_id.to_def_id(), EntryFnType::Start))
121-
} else if let Some((local_def_id, _)) = visitor.attr_main_fn {
121+
} else if let Some((local_def_id, _)) = visitor.rustc_main_fn {
122122
let def_id = local_def_id.to_def_id();
123123
Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) }))
124124
} else {
125+
// The actual resolution of main happens in the resolver, this here
125126
if let Some(main_def) = tcx.resolutions(()).main_def
126127
&& let Some(def_id) = main_def.opt_fn_def_id()
127128
{

Diff for: compiler/rustc_passes/src/errors.rs

-8
Original file line numberDiff line numberDiff line change
@@ -1214,14 +1214,6 @@ pub struct AttrOnlyOnMain {
12141214
pub attr: Symbol,
12151215
}
12161216

1217-
#[derive(Diagnostic)]
1218-
#[diag(passes_attr_only_on_root_main)]
1219-
pub struct AttrOnlyOnRootMain {
1220-
#[primary_span]
1221-
pub span: Span,
1222-
pub attr: Symbol,
1223-
}
1224-
12251217
#[derive(Diagnostic)]
12261218
#[diag(passes_attr_only_in_functions)]
12271219
pub struct AttrOnlyInFunctions {
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![feature(unix_sigpipe)]
22

3-
#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
3+
#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on the root `fn main()`
44
fn f() {}
55

66
fn main() {}

Diff for: tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: `unix_sigpipe` attribute can only be used on `fn main()`
1+
error: `unix_sigpipe` attribute can only be used on the root `fn main()`
22
--> $DIR/unix_sigpipe-non-main-fn.rs:3:1
33
|
44
LL | #[unix_sigpipe = "sig_dfl"]

Diff for: tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![feature(unix_sigpipe)]
22

33
mod m {
4-
#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on root `fn main()`
4+
#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on the root `fn main()`
55
fn main() {}
66
}
77

Diff for: tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: `unix_sigpipe` attribute can only be used on root `fn main()`
1+
error: `unix_sigpipe` attribute can only be used on the root `fn main()`
22
--> $DIR/unix_sigpipe-non-root-main.rs:4:5
33
|
44
LL | #[unix_sigpipe = "sig_dfl"]

Diff for: tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
#![feature(unix_sigpipe)]
33

44
#[start]
5-
#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
5+
#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on the root `fn main()`
66
fn custom_start(argc: isize, argv: *const *const u8) -> isize { 0 }

Diff for: tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: `unix_sigpipe` attribute can only be used on `fn main()`
1+
error: `unix_sigpipe` attribute can only be used on the root `fn main()`
22
--> $DIR/unix_sigpipe-start.rs:5:1
33
|
44
LL | #[unix_sigpipe = "sig_dfl"]
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![feature(unix_sigpipe)]
22

3-
#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
3+
#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on the root `fn main()`
44
struct S;
55

66
fn main() {}

Diff for: tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: `unix_sigpipe` attribute can only be used on `fn main()`
1+
error: `unix_sigpipe` attribute can only be used on the root `fn main()`
22
--> $DIR/unix_sigpipe-struct.rs:3:1
33
|
44
LL | #[unix_sigpipe = "sig_dfl"]

0 commit comments

Comments
 (0)