Skip to content

Commit

Permalink
Initial work for RFC 1260
Browse files Browse the repository at this point in the history
  • Loading branch information
bombless committed Dec 4, 2016
1 parent c80c31a commit 3d891e7
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 9 deletions.
29 changes: 24 additions & 5 deletions src/librustc/middle/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

use dep_graph::DepNode;
use hir::map as ast_map;
use hir::def_id::{CRATE_DEF_INDEX};
use hir::def_id::{CRATE_DEF_INDEX, DefId};
use session::{config, Session};
use syntax::ast::NodeId;
use syntax::attr;
Expand All @@ -36,7 +36,14 @@ struct EntryContext<'a, 'tcx: 'a> {

// The functions that one might think are 'main' but aren't, e.g.
// main functions not defined at the top level. For diagnostics.
non_main_fns: Vec<(NodeId, Span)> ,
non_main_fns: Vec<(NodeId, Span)>,

// Function item that imported to root namespace named 'main'.
// It was collected in resolve phase
defined_as_main: Option<DefId>,

// The function that imported to root namespace named 'main'.
imported_main_fn: Option<(NodeId, Span)>,
}

impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
Expand All @@ -53,7 +60,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
}
}

pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map) {
pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map, defined_as_main: Option<DefId>) {
let _task = ast_map.dep_graph.in_task(DepNode::EntryPoint);

let any_exe = session.crate_types.borrow().iter().any(|ty| {
Expand All @@ -77,6 +84,8 @@ pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map) {
attr_main_fn: None,
start_fn: None,
non_main_fns: Vec::new(),
defined_as_main: defined_as_main,
imported_main_fn: None,
};

ast_map.krate().visit_all_item_likes(&mut ctxt);
Expand All @@ -86,13 +95,15 @@ pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map) {

// Beware, this is duplicated in libsyntax/entry.rs, make sure to keep
// them in sync.
fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType {
fn entry_point_type<F: Fn() -> bool>(item: &Item, at_root: bool, defined_as_main: F) -> EntryPointType {
match item.node {
ItemFn(..) => {
if attr::contains_name(&item.attrs, "start") {
EntryPointType::Start
} else if attr::contains_name(&item.attrs, "main") {
EntryPointType::MainAttr
} else if defined_as_main() {
EntryPointType::ImportedMain
} else if item.name == "main" {
if at_root {
// This is a top-level function so can be 'main'
Expand All @@ -110,7 +121,9 @@ fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType {


fn find_item(item: &Item, ctxt: &mut EntryContext, at_root: bool) {
match entry_point_type(item, at_root) {
match entry_point_type(item,
at_root,
|| ctxt.defined_as_main == Some(ctxt.map.local_def_id(item.id))) {
EntryPointType::MainNamed => {
if ctxt.main_fn.is_none() {
ctxt.main_fn = Some((item.id, item.span));
Expand Down Expand Up @@ -146,6 +159,9 @@ fn find_item(item: &Item, ctxt: &mut EntryContext, at_root: bool) {
.emit();
}
},
EntryPointType::ImportedMain => {
ctxt.imported_main_fn = Some((item.id, item.span));
},
EntryPointType::None => ()
}
}
Expand All @@ -160,6 +176,9 @@ fn configure_main(this: &mut EntryContext) {
} else if this.main_fn.is_some() {
*this.session.entry_fn.borrow_mut() = this.main_fn;
this.session.entry_type.set(Some(config::EntryMain));
} else if this.imported_main_fn.is_some() {
*this.session.entry_fn.borrow_mut() = this.imported_main_fn;
this.session.entry_type.set(Some(config::EntryMain));
} else {
// No main function
let mut err = this.session.struct_err("main function not found");
Expand Down
14 changes: 12 additions & 2 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use rustc::hir;
use rustc::hir::{map as hir_map, FreevarMap, TraitMap};
use rustc::hir::lowering::lower_crate;
use rustc::hir::def_id::DefId;
use rustc_data_structures::blake2b::Blake2bHasher;
use rustc_data_structures::fmt_wrap::FmtWrap;
use rustc::ty::util::ArchIndependentHasher;
Expand Down Expand Up @@ -117,7 +118,12 @@ pub fn compile_input(sess: &Session,

let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess);
let crate_name = link::find_crate_name(Some(sess), &krate.attrs, input);
let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = {
let ExpansionResult { expanded_crate,
defs,
analysis,
resolutions,
defined_as_main,
mut hir_forest } = {
phase_2_configure_and_expand(
sess, &cstore, krate, registry, &crate_name, addl_plugins, control.make_glob_map,
|expanded_crate| {
Expand Down Expand Up @@ -175,6 +181,7 @@ pub fn compile_input(sess: &Session,
resolutions,
&arenas,
&crate_name,
defined_as_main,
|tcx, analysis, incremental_hashes_map, result| {
{
// Eventually, we will want to track plugins.
Expand Down Expand Up @@ -536,6 +543,7 @@ pub struct ExpansionResult {
pub analysis: ty::CrateAnalysis<'static>,
pub resolutions: Resolutions,
pub hir_forest: hir_map::Forest,
pub defined_as_main: Option<DefId>,
}

/// Run the "early phases" of the compiler: initial `cfg` processing,
Expand Down Expand Up @@ -791,6 +799,7 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
hir_ty_to_ty: NodeMap(),
},
defined_as_main: resolver.defined_as_main,
resolutions: Resolutions {
freevars: resolver.freevars,
trait_map: resolver.trait_map,
Expand All @@ -809,6 +818,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
resolutions: Resolutions,
arenas: &'tcx ty::CtxtArenas<'tcx>,
name: &str,
defined_as_main: Option<DefId>,
f: F)
-> Result<R, usize>
where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>,
Expand Down Expand Up @@ -842,7 +852,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,

time(time_passes,
"looking for entry point",
|| middle::entry::find_entry_point(sess, &hir_map));
|| middle::entry::find_entry_point(sess, &hir_map, defined_as_main));

sess.plugin_registrar_fn.set(time(time_passes, "looking for plugin registrar", || {
plugin::build::find_plugin_registrar(sess.diagnostic(), &hir_map)
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_driver/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ impl PpSourceMode {
resolutions.clone(),
arenas,
id,
None,
|tcx, _, _, _| {
let annotation = TypedAnnotation { tcx: tcx };
let _ignore = tcx.dep_graph.in_ignore();
Expand Down Expand Up @@ -960,6 +961,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
resolutions.clone(),
arenas,
crate_name,
None,
|tcx, _, _, _| {
match ppm {
PpmMir | PpmMirCFG => {
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,9 @@ pub struct Resolver<'a> {

// Avoid duplicated errors for "name already defined".
name_already_seen: FxHashMap<Name, Span>,

// Track function imported as main in root namespace
pub defined_as_main: Option<DefId>,
}

pub struct ResolverArenas<'a> {
Expand Down Expand Up @@ -1277,6 +1280,7 @@ impl<'a> Resolver<'a> {
macro_exports: Vec::new(),
invocations: invocations,
name_already_seen: FxHashMap(),
defined_as_main: None,
}
}

Expand Down
7 changes: 6 additions & 1 deletion src/librustc_resolve/resolve_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use self::ImportDirectiveSubclass::*;

use {Module, PerNS};
use Namespace::{self, TypeNS, MacroNS};
use Namespace::{self, TypeNS, MacroNS, ValueNS};
use {NameBinding, NameBindingKind, PathResult, PathScope, PrivacyError, ToNameBinding};
use Resolver;
use {names_to_string, module_to_string};
Expand Down Expand Up @@ -293,6 +293,11 @@ impl<'a> Resolver<'a> {
where T: ToNameBinding<'a>
{
let binding = self.arenas.alloc_name_binding(binding.to_name_binding());
if ns == ValueNS && module.parent.is_none() && name == Name::intern("main") {
if let Def::Fn(def_id) = binding.def() {
self.defined_as_main = Some(def_id);
}
}
self.update_resolution(module, name, ns, |this, resolution| {
if let Some(old_binding) = resolution.binding {
if binding.is_glob_import() {
Expand Down
2 changes: 2 additions & 0 deletions src/libsyntax/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ pub enum EntryPointType {
MainAttr,
Start,
OtherMain, // Not an entry point, but some other function named main
ImportedMain, // function imported as "main" in root namespace
}

// Beware, this is duplicated in librustc/middle/entry.rs, make sure to keep
// them in sync.
// FIXME: get it sync or find other way to keep sane in --test mode
pub fn entry_point_type(item: &Item, depth: usize) -> EntryPointType {
match item.node {
ItemKind::Fn(..) => {
Expand Down
3 changes: 2 additions & 1 deletion src/libsyntax/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ impl fold::Folder for EntryPointCleaner {
// Remove any #[main] or #[start] from the AST so it doesn't
// clash with the one we're going to add, but mark it as
// #[allow(dead_code)] to avoid printing warnings.
let folded = match entry::entry_point_type(&folded, self.depth) {
let folded = match entry::entry_point_type(&folded, self.depth) {
EntryPointType::ImportedMain => unimplemented!(), // FIXME
EntryPointType::MainNamed |
EntryPointType::MainAttr |
EntryPointType::Start =>
Expand Down

0 comments on commit 3d891e7

Please sign in to comment.