Skip to content
Permalink
Browse files

Rollup merge of rust-lang#57573 - Xanewok:querify-entry-fn, r=Zoxc

Querify `entry_fn`

Analogous to rust-lang#57570 but this will also require few fixups in Miri so I decided to separate that (and it seems [CI doesn't let us break tools anymore](rust-lang#57392 (comment))? Or was that because it was a rollup PR?)

r? @nikomatsakis
  • Loading branch information...
Centril committed Jan 19, 2019
2 parents b941f29 + b7cd24d commit 64eb69b904513b8f277102e4c802527e718debdc
@@ -583,6 +583,7 @@ define_dep_nodes!( <'tcx>
[] CheckImplItemWellFormed(DefId),
[] ReachableNonGenerics(CrateNum),
[] NativeLibraries(CrateNum),
[] EntryFn(CrateNum),
[] PluginRegistrarFn(CrateNum),
[] ProcMacroDeclsStatic(CrateNum),
[input] CrateDisambiguator(CrateNum),
@@ -409,7 +409,7 @@ fn create_and_seed_worklist<'a, 'tcx>(
}
}).chain(
// Seed entry point
tcx.sess.entry_fn.borrow().map(|(id, _, _)| id)
tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().as_local_node_id(def_id).unwrap())
).collect::<Vec<_>>();

// Seed implemented trait items
@@ -1,5 +1,5 @@
use hir::map as hir_map;
use hir::def_id::{CRATE_DEF_INDEX};
use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
use session::{config, Session};
use session::config::EntryFnType;
use syntax::ast::NodeId;
@@ -8,6 +8,8 @@ use syntax::entry::EntryPointType;
use syntax_pos::Span;
use hir::{Item, ItemKind, ImplItem, TraitItem};
use hir::itemlikevisit::ItemLikeVisitor;
use ty::TyCtxt;
use ty::query::Providers;

struct EntryContext<'a, 'tcx: 'a> {
session: &'a Session,
@@ -45,36 +47,34 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
}
}

pub fn find_entry_point(session: &Session,
hir_map: &hir_map::Map<'_>,
crate_name: &str) {
let any_exe = session.crate_types.borrow().iter().any(|ty| {
fn entry_fn(tcx: TyCtxt<'_, '_, '_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> {
assert_eq!(cnum, LOCAL_CRATE);

let any_exe = tcx.sess.crate_types.borrow().iter().any(|ty| {
*ty == config::CrateType::Executable
});
if !any_exe {
// No need to find a main function
session.entry_fn.set(None);
return
return None;
}

// If the user wants no main function at all, then stop here.
if attr::contains_name(&hir_map.krate().attrs, "no_main") {
session.entry_fn.set(None);
return
if attr::contains_name(&tcx.hir().krate().attrs, "no_main") {
return None;
}

let mut ctxt = EntryContext {
session,
map: hir_map,
session: tcx.sess,
map: tcx.hir(),
main_fn: None,
attr_main_fn: None,
start_fn: None,
non_main_fns: Vec::new(),
};

hir_map.krate().visit_all_item_likes(&mut ctxt);
tcx.hir().krate().visit_all_item_likes(&mut ctxt);

configure_main(&mut ctxt, crate_name);
configure_main(tcx, &ctxt)
}

// Beware, this is duplicated in `libsyntax/entry.rs`, so make sure to keep
@@ -135,43 +135,58 @@ fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
.span_label(item.span, "multiple `start` functions")
.emit();
}
},
EntryPointType::None => ()
}
EntryPointType::None => (),
}
}

fn configure_main(this: &mut EntryContext<'_, '_>, crate_name: &str) {
if let Some((node_id, span)) = this.start_fn {
this.session.entry_fn.set(Some((node_id, span, EntryFnType::Start)));
} else if let Some((node_id, span)) = this.attr_main_fn {
this.session.entry_fn.set(Some((node_id, span, EntryFnType::Main)));
} else if let Some((node_id, span)) = this.main_fn {
this.session.entry_fn.set(Some((node_id, span, EntryFnType::Main)));
fn configure_main(
tcx: TyCtxt<'_, '_, '_>,
visitor: &EntryContext<'_, '_>,
) -> Option<(DefId, EntryFnType)> {
if let Some((node_id, _)) = visitor.start_fn {
Some((tcx.hir().local_def_id(node_id), EntryFnType::Start))
} else if let Some((node_id, _)) = visitor.attr_main_fn {
Some((tcx.hir().local_def_id(node_id), EntryFnType::Main))
} else if let Some((node_id, _)) = visitor.main_fn {
Some((tcx.hir().local_def_id(node_id), EntryFnType::Main))
} 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() {
let mut err = struct_err!(tcx.sess, E0601,
"`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE));
if !visitor.non_main_fns.is_empty() {
// There were some functions named 'main' though. Try to give the user a hint.
err.note("the main function must be defined at the crate level \
but you have one or more functions named 'main' that are not \
defined at the crate level. Either move the definition or \
attach the `#[main]` attribute to override this behavior.");
for &(_, span) in &this.non_main_fns {
for &(_, span) in &visitor.non_main_fns {
err.span_note(span, "here is a function named 'main'");
}
err.emit();
this.session.abort_if_errors();
tcx.sess.abort_if_errors();
} else {
if let Some(ref filename) = this.session.local_crate_source_file {
if let Some(ref filename) = tcx.sess.local_crate_source_file {
err.note(&format!("consider adding a `main` function to `{}`", filename.display()));
}
if this.session.teach(&err.get_code().unwrap()) {
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 \
to get started: https://doc.rust-lang.org/book/");
}
err.emit();
}

None
}
}

pub fn find_entry_point(tcx: TyCtxt<'_, '_, '_>) -> Option<(DefId, EntryFnType)> {
tcx.entry_fn(LOCAL_CRATE)
}

pub fn provide(providers: &mut Providers<'_>) {
*providers = Providers {
entry_fn,
..*providers
};
}
@@ -649,15 +649,15 @@ impl Options {
}
}

// The type of entry function, so
// users can have their own entry
// functions
#[derive(Copy, Clone, PartialEq)]
// The type of entry function, so users can have their own entry functions
#[derive(Copy, Clone, PartialEq, Hash, Debug)]
pub enum EntryFnType {
Main,
Start,
}

impl_stable_hash_via_hash!(EntryFnType);

#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
pub enum CrateType {
Executable,
@@ -67,8 +67,6 @@ pub struct Session {
/// This is `None` if the host and target are the same.
pub target_tlib_path: Option<SearchPath>,
pub parse_sess: ParseSess,
/// For a library crate, this is always none
pub entry_fn: Once<Option<(NodeId, Span, config::EntryFnType)>>,
pub sysroot: PathBuf,
/// The name of the root source file of the crate, in the local file system.
/// `None` means that there is no source file.
@@ -1173,8 +1171,6 @@ pub fn build_session_(
host_tlib_path,
target_tlib_path,
parse_sess: p_s,
// For a library crate, this is always none
entry_fn: Once::new(),
sysroot,
local_crate_source_file,
working_dir,
@@ -629,6 +629,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::foreign_modules<'tcx> {
}
}

impl<'tcx> QueryDescription<'tcx> for queries::entry_fn<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"looking up the entry function of a crate".into()
}
}

impl<'tcx> QueryDescription<'tcx> for queries::plugin_registrar_fn<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"looking up the plugin registrar for a crate".into()
@@ -22,7 +22,7 @@ use mir::mono::CodegenUnit;
use mir;
use mir::interpret::GlobalId;
use session::{CompileResult, CrateDisambiguator};
use session::config::OutputFilenames;
use session::config::{EntryFnType, OutputFilenames};
use traits::{self, Vtable};
use traits::query::{
CanonicalPredicateGoal, CanonicalProjectionGoal,
@@ -476,6 +476,9 @@ define_queries! { <'tcx>

[] fn foreign_modules: ForeignModules(CrateNum) -> Lrc<Vec<ForeignModule>>,

/// Identifies the entry-point (e.g. the `main` function) for a given
/// crate, returning `None` if there is no entry point (such as for library crates).
[] fn entry_fn: EntryFn(CrateNum) -> Option<(DefId, EntryFnType)>,
[] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option<DefId>,
[] fn proc_macro_decls_static: ProcMacroDeclsStatic(CrateNum) -> Option<DefId>,
[] fn crate_disambiguator: CrateDisambiguator(CrateNum) -> CrateDisambiguator,
@@ -1329,6 +1329,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
DepKind::CheckImplItemWellFormed => { force!(check_impl_item_well_formed, def_id!()); }
DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); }
DepKind::NativeLibraries => { force!(native_libraries, krate!()); }
DepKind::EntryFn => { force!(entry_fn, krate!()); }
DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); }
DepKind::ProcMacroDeclsStatic => { force!(proc_macro_decls_static, krate!()); }
DepKind::CrateDisambiguator => { force!(crate_disambiguator, krate!()); }
@@ -14,7 +14,7 @@ use llvm;
use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DISubprogram, DIArray, DIFlags,
DILexicalBlock};
use rustc::hir::CodegenFnAttrFlags;
use rustc::hir::def_id::{DefId, CrateNum};
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
use rustc::ty::subst::{Substs, UnpackedKind};

use abi::Abi;
@@ -290,9 +290,8 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {

let mut flags = DIFlags::FlagPrototyped;

let local_id = self.tcx().hir().as_local_node_id(def_id);
if let Some((id, _, _)) = *self.sess().entry_fn.borrow() {
if local_id == Some(id) {
if let Some((id, _)) = self.tcx.entry_fn(LOCAL_CRATE) {
if id == def_id {
flags |= DIFlags::FlagMainSubprogram;
}
}
@@ -194,7 +194,7 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
})
.collect();

if tcx.sess.entry_fn.borrow().is_some() {
if tcx.entry_fn(LOCAL_CRATE).is_some() {
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new("main"));

symbols.push((exported_symbol, SymbolExportLevel::C));
@@ -441,10 +441,8 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
pub fn maybe_create_entry_wrapper<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
cx: &'a Bx::CodegenCx
) {
let (main_def_id, span) = match *cx.sess().entry_fn.borrow() {
Some((id, span, _)) => {
(cx.tcx().hir().local_def_id(id), span)
}
let (main_def_id, span) = match cx.tcx().entry_fn(LOCAL_CRATE) {
Some((def_id, _)) => { (def_id, cx.tcx().def_span(def_id)) },
None => return,
};

@@ -458,7 +456,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(

let main_llfn = cx.get_fn(instance);

let et = cx.sess().entry_fn.get().map(|e| e.2);
let et = cx.tcx().entry_fn(LOCAL_CRATE).map(|e| e.1);
match et {
Some(EntryFnType::Main) => create_entry_fn::<Bx>(cx, span, main_llfn, main_def_id, true),
Some(EntryFnType::Start) => create_entry_fn::<Bx>(cx, span, main_llfn, main_def_id, false),
@@ -31,6 +31,7 @@ extern crate syntax_pos;
#[macro_use] extern crate rustc_data_structures;

use rustc::ty::TyCtxt;
use rustc::hir::def_id::LOCAL_CRATE;

pub mod link;
pub mod codegen_backend;
@@ -42,11 +43,9 @@ pub mod symbol_names_test;
/// 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() {
let main_def_id = tcx.hir().local_def_id(id);

if tcx.has_attr(main_def_id, "rustc_error") {
tcx.sess.span_fatal(span, "compilation successful");
if let Some((def_id, _)) = tcx.entry_fn(LOCAL_CRATE) {
if tcx.has_attr(def_id, "rustc_error") {
tcx.sess.span_fatal(tcx.def_span(def_id), "compilation successful");
}
}
}
@@ -1149,6 +1149,7 @@ pub fn default_provide(providers: &mut ty::query::Providers) {
rustc_passes::provide(providers);
rustc_traits::provide(providers);
middle::region::provide(providers);
middle::entry::provide(providers);
cstore::provide(providers);
lint::provide(providers);
}
@@ -1183,10 +1184,6 @@ where
rustc_incremental::load_query_result_cache(sess)
});

time(sess, "looking for entry point", || {
middle::entry::find_entry_point(sess, &hir_map, name)
});

let mut local_providers = ty::query::Providers::default();
default_provide(&mut local_providers);
codegen_backend.provide(&mut local_providers);
@@ -1216,6 +1213,10 @@ where
// tcx available.
time(sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));

time(sess, "looking for entry point", || {
middle::entry::find_entry_point(tcx)
});

time(sess, "looking for plugin registrar", || {
plugin::build::find_plugin_registrar(tcx)
});
Oops, something went wrong.

0 comments on commit 64eb69b

Please sign in to comment.
You can’t perform that action at this time.