Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement RFC 1260 with feature_name imported_main. #84401

Merged
merged 1 commit into from
Apr 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/driver/jit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
});

let (main_def_id, entry_ty) = tcx.entry_fn(LOCAL_CRATE).unwrap();
let instance = Instance::mono(tcx, main_def_id.to_def_id()).polymorphize(tcx);
let instance = Instance::mono(tcx, main_def_id).polymorphize(tcx);

match entry_ty {
EntryFnType::Main => {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/main_shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub(crate) fn maybe_create_entry_wrapper(
) {
let (main_def_id, use_start_lang_item) = match tcx.entry_fn(LOCAL_CRATE) {
Some((def_id, entry_ty)) => (
def_id.to_def_id(),
def_id,
match entry_ty {
EntryFnType::Main => true,
EntryFnType::Start => false,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
spflags |= DISPFlags::SPFlagOptimized;
}
if let Some((id, _)) = self.tcx.entry_fn(LOCAL_CRATE) {
if id.to_def_id() == def_id {
if id == def_id {
spflags |= DISPFlags::SPFlagMainSubprogram;
}
}
Expand Down
27 changes: 22 additions & 5 deletions compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
use rustc_data_structures::sync::{par_iter, ParallelIterator};
use rustc_hir as hir;
use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::lang_items::LangItem;
use rustc_index::vec::Idx;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
Expand Down Expand Up @@ -348,12 +348,29 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
cx: &'a Bx::CodegenCx,
) -> Option<Bx::Function> {
let main_def_id = cx.tcx().entry_fn(LOCAL_CRATE).map(|(def_id, _)| def_id)?;
let instance = Instance::mono(cx.tcx(), main_def_id.to_def_id());
let main_is_local = main_def_id.is_local();
let instance = Instance::mono(cx.tcx(), main_def_id);

if !cx.codegen_unit().contains_item(&MonoItem::Fn(instance)) {
if main_is_local {
// We want to create the wrapper in the same codegen unit as Rust's main
// function.
return None;
if !cx.codegen_unit().contains_item(&MonoItem::Fn(instance)) {
return None;
}
} else {
// FIXME: Add support for non-local main fn codegen
let span = cx.tcx().main_def.unwrap().span;
let n = 28937;
cx.sess()
.struct_span_err(span, "entry symbol `main` from foreign crate is not yet supported.")
.note(&format!(
"see issue #{} <https://github.com/rust-lang/rust/issues/{}> \
for more information",
n, n,
))
.emit();
cx.sess().abort_if_errors();
bug!();
}
petrochenkov marked this conversation as resolved.
Show resolved Hide resolved

let main_llfn = cx.get_fn_addr(instance);
Expand All @@ -366,7 +383,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
cx: &'a Bx::CodegenCx,
rust_main: Bx::Value,
rust_main_def_id: LocalDefId,
rust_main_def_id: DefId,
use_start_lang_item: bool,
) -> Bx::Function {
// The entry function is either `int main(void)` or `int main(int argc, char **argv)`,
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_error_codes/src/error_codes/E0136.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#### Note: this error code is no longer emitted by the compiler.

More than one `main` function was found.

Erroneous code example:

```compile_fail,E0136
```compile_fail
fn main() {
// ...
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use rustc_attr::{self as attr, is_builtin_attr};
use rustc_data_structures::map_in_place::MapInPlace;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, PResult};
use rustc_errors::{Applicability, FatalError, PResult};
use rustc_feature::Features;
use rustc_parse::parser::{AttemptLocalParseRecovery, ForceCollect, Parser, RecoverComma};
use rustc_parse::validate_attr;
Expand Down Expand Up @@ -414,6 +414,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
kind.article(), kind.descr()
),
);
// FIXME: this workaround issue #84569
FatalError.raise();
crlf0710 marked this conversation as resolved.
Show resolved Hide resolved
}
};
self.cx.trace_macros_diag();
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,9 @@ declare_features! (
/// Allows unsizing coercions in `const fn`.
(active, const_fn_unsize, "1.53.0", Some(64992), None),

/// Allows using imported `main` function
(active, imported_main, "1.53.0", Some(28937), None),

// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_interface/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ impl<'tcx> Queries<'tcx> {
_ => return,
};

let attrs = &*tcx.get_attrs(def_id.to_def_id());
let attrs = &*tcx.get_attrs(def_id);
let attrs = attrs.iter().filter(|attr| tcx.sess.check_name(attr, sym::rustc_error));
for attr in attrs {
match attr.meta_item_list() {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/mir/mono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rustc_data_structures::base_n;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_hir::{HirId, ItemId};
use rustc_session::config::OptLevel;
use rustc_span::source_map::Span;
Expand Down Expand Up @@ -93,7 +93,7 @@ impl<'tcx> MonoItem<'tcx> {
// indicator, then we'll be creating a globally shared version.
if tcx.codegen_fn_attrs(instance.def_id()).contains_extern_indicator()
|| !instance.def.generates_cgu_internal_copy(tcx)
|| Some(instance.def_id()) == entry_def_id.map(LocalDefId::to_def_id)
|| Some(instance.def_id()) == entry_def_id
{
return InstantiationMode::GloballyShared { may_conflict: false };
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@ rustc_queries! {

/// 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).
query entry_fn(_: CrateNum) -> Option<(LocalDefId, EntryFnType)> {
query entry_fn(_: CrateNum) -> Option<(DefId, EntryFnType)> {
desc { "looking up the entry function of a crate" }
}
query plugin_registrar_fn(_: CrateNum) -> Option<DefId> {
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ use crate::ty::TyKind::*;
use crate::ty::{
self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid,
DefIdTree, ExistentialPredicate, FloatTy, FloatVar, FloatVid, GenericParamDefKind, InferConst,
InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate,
PredicateInner, PredicateKind, ProjectionTy, Region, RegionKind, ReprOptions,
InferTy, IntTy, IntVar, IntVid, List, MainDefinition, ParamConst, ParamTy, PolyFnSig,
Predicate, PredicateInner, PredicateKind, ProjectionTy, Region, RegionKind, ReprOptions,
TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy, Visibility,
};
use rustc_ast as ast;
Expand Down Expand Up @@ -1025,6 +1025,8 @@ pub struct GlobalCtxt<'tcx> {
layout_interner: ShardedHashMap<&'tcx Layout, ()>,

output_filenames: Arc<OutputFilenames>,

pub main_def: Option<MainDefinition>,
}

impl<'tcx> TyCtxt<'tcx> {
Expand Down Expand Up @@ -1185,6 +1187,7 @@ impl<'tcx> TyCtxt<'tcx> {
const_stability_interner: Default::default(),
alloc_map: Lock::new(interpret::AllocMap::new()),
output_filenames: Arc::new(output_filenames.clone()),
main_def: resolutions.main_def,
}
}

Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,20 @@ pub struct ResolverOutputs {
/// Extern prelude entries. The value is `true` if the entry was introduced
/// via `extern crate` item and not `--extern` option or compiler built-in.
pub extern_prelude: FxHashMap<Symbol, bool>,
pub main_def: Option<MainDefinition>,
}

#[derive(Clone, Copy)]
pub struct MainDefinition {
pub res: Res<ast::NodeId>,
pub is_import: bool,
pub span: Span,
}

impl MainDefinition {
pub fn opt_fn_def_id(self) -> Option<DefId> {
if let Res::Def(DefKind::Fn, def_id) = self.res { Some(def_id) } else { None }
}
}

/// The "header" of an impl is everything outside the body: a Self type, a trait
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir/src/monomorphize/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1066,7 +1066,7 @@ struct RootCollector<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
mode: MonoItemCollectionMode,
output: &'a mut Vec<Spanned<MonoItem<'tcx>>>,
entry_fn: Option<(LocalDefId, EntryFnType)>,
entry_fn: Option<(DefId, EntryFnType)>,
}

impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
Expand Down Expand Up @@ -1154,7 +1154,7 @@ impl RootCollector<'_, 'v> {
&& match self.mode {
MonoItemCollectionMode::Eager => true,
MonoItemCollectionMode::Lazy => {
self.entry_fn.map(|(id, _)| id) == Some(def_id)
self.entry_fn.and_then(|(id, _)| id.as_local()) == Some(def_id)
|| self.tcx.is_reachable_non_generic(def_id)
|| self
.tcx
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_passes/src/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,9 @@ fn create_and_seed_worklist<'tcx>(
)
.chain(
// Seed entry point
tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().local_def_id_to_hir_id(def_id)),
tcx.entry_fn(LOCAL_CRATE).and_then(|(def_id, _)| {
def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
}),
)
.collect::<Vec<_>>();

Expand Down
51 changes: 28 additions & 23 deletions compiler/rustc_passes/src/entry.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand All @@ -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)>,

Expand Down Expand Up @@ -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);
Expand All @@ -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(),
Expand Down Expand Up @@ -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));
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 \
Expand All @@ -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)
}

Expand Down
Loading