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.
This commit is contained in:
parent
6d721dd0b8
commit
1572c0dcd7
5 changed files with 49 additions and 43 deletions
|
@ -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()
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue