}
// Seed entry point
- if let Some((id, _)) = *tcx.sess.entry_fn.borrow() {
+ if let Some((id, _, _)) = *tcx.sess.entry_fn.borrow() {
worklist.push(id);
}
});
if !any_exe {
// No need to find a main function
+ session.entry_fn.set(None);
return
}
// If the user wants no main function at all, then stop here.
if attr::contains_name(&hir_map.krate().attrs, "no_main") {
- session.entry_type.set(Some(config::EntryNone));
+ session.entry_fn.set(None);
return
}
}
fn configure_main(this: &mut EntryContext, crate_name: &str) {
- if this.start_fn.is_some() {
- *this.session.entry_fn.borrow_mut() = this.start_fn;
- this.session.entry_type.set(Some(config::EntryStart));
- } else if this.attr_main_fn.is_some() {
- *this.session.entry_fn.borrow_mut() = this.attr_main_fn;
- this.session.entry_type.set(Some(config::EntryMain));
- } else if this.main_fn.is_some() {
- *this.session.entry_fn.borrow_mut() = this.main_fn;
- this.session.entry_type.set(Some(config::EntryMain));
+ if let Some((node_id, span)) = this.start_fn {
+ this.session.entry_fn.set(Some((node_id, span, config::EntryStart)));
+ } else if let Some((node_id, span)) = this.attr_main_fn {
+ this.session.entry_fn.set(Some((node_id, span, config::EntryMain)));
+ } else if let Some((node_id, span)) = this.main_fn {
+ this.session.entry_fn.set(Some((node_id, span, config::EntryMain)));
} else {
// No main function
+ this.session.entry_fn.set(None);
let mut err = struct_err!(this.session, E0601,
"`main` function not found in crate `{}`", crate_name);
if !this.non_main_fns.is_empty() {
// The type of entry function, so
// users can have their own entry
-// functions that don't start a
-// scheduler
+// functions
#[derive(Copy, Clone, PartialEq)]
pub enum EntryFnType {
EntryMain,
EntryStart,
- EntryNone,
}
#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
pub opts: config::Options,
pub parse_sess: ParseSess,
/// For a library crate, this is always none
- pub entry_fn: RefCell<Option<(NodeId, Span)>>,
- pub entry_type: Cell<Option<config::EntryFnType>>,
+ pub entry_fn: Once<Option<(NodeId, Span, config::EntryFnType)>>,
pub plugin_registrar_fn: Cell<Option<ast::NodeId>>,
pub derive_registrar_fn: Cell<Option<ast::NodeId>>,
pub default_sysroot: Option<PathBuf>,
opts: sopts,
parse_sess: p_s,
// For a library crate, this is always none
- entry_fn: RefCell::new(None),
- entry_type: Cell::new(None),
+ entry_fn: Once::new(),
plugin_registrar_fn: Cell::new(None),
derive_registrar_fn: Cell::new(None),
default_sysroot,
let mut roots = Vec::new();
{
- let entry_fn = tcx.sess.entry_fn.borrow().map(|(node_id, _)| {
+ let entry_fn = tcx.sess.entry_fn.borrow().map(|(node_id, _, _)| {
tcx.hir.local_def_id(node_id)
});
/// the return type of `main`. This is not needed when
/// the user writes their own `start` manually.
fn push_extra_entry_roots(&mut self) {
- if self.tcx.sess.entry_type.get() != Some(config::EntryMain) {
+ if self.tcx.sess.entry_fn.get().map(|e| e.2) != Some(config::EntryMain) {
return
}
match *self.as_mono_item() {
MonoItem::Fn(ref instance) => {
let entry_def_id =
- tcx.sess.entry_fn.borrow().map(|(id, _)| tcx.hir.local_def_id(id));
+ tcx.sess.entry_fn.borrow().map(|(id, _, _)| tcx.hir.local_def_id(id));
// If this function isn't inlined or otherwise has explicit
// linkage, then we'll be creating a globally shared version.
if self.explicit_linkage(tcx).is_some() ||
/// users main function.
fn maybe_create_entry_wrapper(cx: &CodegenCx) {
let (main_def_id, span) = match *cx.sess().entry_fn.borrow() {
- Some((id, span)) => {
+ Some((id, span, _)) => {
(cx.tcx.hir.local_def_id(id), span)
}
None => return,
let main_llfn = callee::get_fn(cx, instance);
- let et = cx.sess().entry_type.get().unwrap();
+ let et = cx.sess().entry_fn.get().map(|e| e.2);
match et {
- config::EntryMain => create_entry_fn(cx, span, main_llfn, main_def_id, true),
- config::EntryStart => create_entry_fn(cx, span, main_llfn, main_def_id, false),
- config::EntryNone => {} // Do nothing.
+ Some(config::EntryMain) => create_entry_fn(cx, span, main_llfn, main_def_id, true),
+ Some(config::EntryStart) => create_entry_fn(cx, span, main_llfn, main_def_id, false),
+ None => {} // Do nothing.
}
fn create_entry_fn<'cx>(cx: &'cx CodegenCx,
let local_id = cx.tcx.hir.as_local_node_id(def_id);
match *cx.sess().entry_fn.borrow() {
- Some((id, _)) => {
+ Some((id, _, _)) => {
if local_id == Some(id) {
flags = flags | DIFlags::FlagMainSubprogram;
}
/// that actually test that compilation succeeds without
/// reporting an error.
pub fn check_for_rustc_errors_attr(tcx: TyCtxt) {
- if let Some((id, span)) = *tcx.sess.entry_fn.borrow() {
+ if let Some((id, span, _)) = *tcx.sess.entry_fn.borrow() {
let main_def_id = tcx.hir.local_def_id(id);
if tcx.has_attr(main_def_id, "rustc_error") {
// Check that the main return type implements the termination trait.
if let Some(term_id) = fcx.tcx.lang_items().termination() {
- if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() {
+ if let Some((id, _, entry_type)) = *fcx.tcx.sess.entry_fn.borrow() {
if id == fn_id {
- match fcx.sess().entry_type.get() {
- Some(config::EntryMain) => {
+ match entry_type {
+ config::EntryMain => {
let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty)));
let trait_ref = ty::TraitRef::new(term_id, substs);
let return_ty_span = decl.output.span();
traits::Obligation::new(
cause, param_env, trait_ref.to_predicate()));
},
- _ => {},
+ config::EntryStart => {},
}
}
}
}
fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
- if let Some((id, sp)) = *tcx.sess.entry_fn.borrow() {
- match tcx.sess.entry_type.get() {
- Some(config::EntryMain) => check_main_fn_ty(tcx, id, sp),
- Some(config::EntryStart) => check_start_fn_ty(tcx, id, sp),
- Some(config::EntryNone) => {}
- None => bug!("entry function without a type")
+ if let Some((id, sp, entry_type)) = *tcx.sess.entry_fn.borrow() {
+ match entry_type {
+ config::EntryMain => check_main_fn_ty(tcx, id, sp),
+ config::EntryStart => check_start_fn_ty(tcx, id, sp),
}
}
}