1
Fork 0

Implement RFC 1260 with feature_name imported_main.

This commit is contained in:
Charles Lew 2021-04-26 01:09:35 +08:00
parent 727d101561
commit d261df4a72
38 changed files with 463 additions and 193 deletions

View file

@ -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)
}