Implement RFC 1260 with feature_name imported_main
.
This commit is contained in:
parent
727d101561
commit
d261df4a72
38 changed files with 463 additions and 193 deletions
|
@ -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(¬e);
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue