diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs deleted file mode 100644 index 290f6006de079..0000000000000 --- a/compiler/rustc_ast/src/entry.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub enum EntryPointType { - None, - MainNamed, - MainAttr, - Start, - OtherMain, // Not an entry point, but some other function named main -} diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 1e6da044ec039..867ad62e04d63 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -43,7 +43,6 @@ pub mod util { pub mod ast; pub mod ast_like; pub mod attr; -pub mod entry; pub mod expand; pub mod mut_visit; pub mod node_id; diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index cd5d116964f62..cdd0ff4a38252 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -48,7 +48,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use rustc_errors::struct_span_err; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res}; +use rustc_hir::def::{DefKind, EntryFn, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, CRATE_DEF_ID}; use rustc_hir::definitions::{DefKey, DefPathData, Definitions}; use rustc_hir::intravisit; @@ -171,6 +171,8 @@ struct LoweringContext<'a, 'hir: 'a> { allow_try_trait: Option>, allow_gen_future: Option>, + + entry_fn_attr: Option, } pub trait ResolverAstLowering { @@ -211,6 +213,12 @@ pub trait ResolverAstLowering { expn_id: ExpnId, span: Span, ) -> LocalDefId; + + fn resolve_ast_path_in_value_ns( + &mut self, + path: &Path, + module_id: DefId, + ) -> Option>; } type NtToTokenstream = fn(&Nonterminal, &ParseSess, CanSynthesizeMissingTokens) -> TokenStream; @@ -334,6 +342,7 @@ pub fn lower_crate<'a, 'hir>( in_scope_lifetimes: Vec::new(), allow_try_trait: Some([sym::try_trait][..].into()), allow_gen_future: Some([sym::gen_future][..].into()), + entry_fn_attr: None, } .lower_crate(krate) } @@ -547,6 +556,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }) .collect(); + self.lower_entry_fn(&c.attrs); + let mut def_id_to_hir_id = IndexVec::default(); for (node_id, hir_id) in self.node_id_to_hir_id.into_iter_enumerated() { @@ -583,6 +594,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { proc_macros, trait_map, attrs: self.attrs, + entry_fn_attr: self.entry_fn_attr, } } @@ -2468,6 +2480,69 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } + fn lower_entry_fn(&mut self, attrs: &[Attribute]) { + let sess = self.sess; + let resolver = &mut *self.resolver; + let entry_fn = &mut self.entry_fn_attr; + + fn copy_path_to_use_node_id(path: &Path, node_id: NodeId) -> Path { + let mut path = path.clone(); + path.segments.iter_mut().for_each(|seg| { + seg.id = node_id; + }); + path + } + + let mut ignored_entry_fns = vec![]; + for rustc_main_attr in attrs.iter().filter(|attr| attr.has_name(sym::rustc_main)) { + let attr_meta_item = rustc_main_attr.meta_item_list(); + let sp = rustc_main_attr.span; + let mut is_ignored = false; + let (path, is_naked) = match attr_meta_item.as_ref().map(Vec::as_slice) { + Some([NestedMetaItem::MetaItem(MetaItem { path, .. })]) => (path, false), + Some([NestedMetaItem::MetaItem(MetaItem { path, .. }), naked]) + if naked.has_name(sym::naked) => + { + (path, true) + } + Some([NestedMetaItem::MetaItem(MetaItem { path, .. }), ignore]) + if ignore.has_name(sym::ignore) => + { + is_ignored = true; + (path, false) + } + _ => { + sess.struct_span_err(sp, "incorrect #[rustc_main] attribute format").emit(); + continue; + } + }; + let entry_fn_node_id = resolver.next_node_id(); + let entry_fn_node_path = copy_path_to_use_node_id(path, entry_fn_node_id); + + let local_def_id = match resolver + .resolve_ast_path_in_value_ns(&entry_fn_node_path, CRATE_DEF_ID.to_def_id()) + { + Some(Res::Def(DefKind::Fn, def_id)) => def_id.as_local(), + _ => None, + }; + + if is_ignored { + ignored_entry_fns.extend(local_def_id); + continue; + } + + if let Some(local_def_id) = local_def_id { + *entry_fn = Some(EntryFn { local_def_id, is_naked, ignored_local_def_ids: vec![] }) + } else { + sess.struct_span_err(sp, "#[rustc_main] resolution failure").emit(); + continue; + } + } + if let Some(entry_fn) = entry_fn { + entry_fn.ignored_local_def_ids.extend(ignored_entry_fns.into_iter()); + } + } + // Helper methods for building HIR. fn stmt(&mut self, span: Span, kind: hir::StmtKind<'hir>) -> hir::Stmt<'hir> { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 87c4bfae1af23..f6b18bdea51ab 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -366,16 +366,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { over time" ); } - if self.sess.contains_name(&i.attrs[..], sym::main) { - gate_feature_post!( - &self, - main, - i.span, - "declaration of a non-standard `#[main]` \ - function may change over time, for now \ - a top-level `fn main()` is required" - ); - } } ast::ItemKind::Struct(..) => { diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 28e8259784387..5b0059b5cbfc2 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -1,13 +1,13 @@ // Code that generates a test runner to run all the tests in a crate use rustc_ast as ast; -use rustc_ast::entry::EntryPointType; use rustc_ast::mut_visit::{ExpectOne, *}; use rustc_ast::ptr::P; use rustc_ast::{attr, ModKind}; use rustc_expand::base::{ExtCtxt, ResolverExpand}; use rustc_expand::expand::{AstFragment, ExpansionConfig}; use rustc_feature::Features; +use rustc_session::config::CrateType; use rustc_session::Session; use rustc_span::hygiene::{AstPass, SyntaxContext, Transparency}; use rustc_span::symbol::{sym, Ident, Symbol}; @@ -88,8 +88,9 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { fn visit_crate(&mut self, c: &mut ast::Crate) { noop_visit_crate(c, self); - // Create a main function to run our tests - c.items.push(mk_main(&mut self.cx)); + ensure_exist_rustc_main_attr(&mut self.cx, &mut c.attrs); + // Create an entry function to run our tests + mk_entry_fn(&mut self.cx, c); } fn flat_map_item(&mut self, i: P) -> SmallVec<[P; 1]> { @@ -124,7 +125,7 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { Some(parent), ); for test in &mut tests { - // See the comment on `mk_main` for why we're using + // See the comment on `mk_entry_fn` for why we're using // `apply_mark` directly. test.ident.span = test.ident.span.apply_mark(expn_id, Transparency::Opaque); } @@ -135,28 +136,32 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { } } -// Beware, this is duplicated in librustc_passes/entry.rs (with -// `rustc_hir::Item`), so make sure to keep them in sync. -fn entry_point_type(sess: &Session, item: &ast::Item, depth: usize) -> EntryPointType { - match item.kind { - ast::ItemKind::Fn(..) => { - if sess.contains_name(&item.attrs, sym::start) { - EntryPointType::Start - } else if sess.contains_name(&item.attrs, sym::main) { - EntryPointType::MainAttr - } else if item.ident.name == sym::main { - if depth == 1 { - // This is a top-level function so can be 'main' - EntryPointType::MainNamed - } else { - EntryPointType::OtherMain - } - } else { - EntryPointType::None - } - } - _ => EntryPointType::None, +/// Remove any #[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. +fn strip_start_attr(sess: &Session, def_site: Span, item: P) -> P { + if !matches!(item.kind, ast::ItemKind::Fn(..)) { + return item; } + if !sess.contains_name(&item.attrs, sym::start) { + return item; + } + + item.map(|item| { + let ast::Item { id, ident, attrs, kind, vis, span, tokens } = item; + + let allow_ident = Ident::new(sym::allow, def_site); + let dc_nested = attr::mk_nested_word_item(Ident::new(sym::dead_code, def_site)); + let allow_dead_code_item = attr::mk_list_item(allow_ident, vec![dc_nested]); + let allow_dead_code = attr::mk_attr_outer(allow_dead_code_item); + let attrs = attrs + .into_iter() + .filter(|attr| !sess.check_name(attr, sym::start)) + .chain(iter::once(allow_dead_code)) + .collect(); + + ast::Item { id, ident, attrs, kind, vis, span, tokens } + }) } /// A folder used to remove any entry points (like fn main) because the harness /// generator will provide its own @@ -172,33 +177,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> { self.depth += 1; let item = noop_flat_map_item(i, self).expect_one("noop did something"); self.depth -= 1; - - // 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 item = match entry_point_type(self.sess, &item, self.depth) { - EntryPointType::MainNamed | EntryPointType::MainAttr | EntryPointType::Start => item - .map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| { - let allow_ident = Ident::new(sym::allow, self.def_site); - let dc_nested = - attr::mk_nested_word_item(Ident::new(sym::dead_code, self.def_site)); - let allow_dead_code_item = attr::mk_list_item(allow_ident, vec![dc_nested]); - let allow_dead_code = attr::mk_attr_outer(allow_dead_code_item); - let attrs = attrs - .into_iter() - .filter(|attr| { - !self.sess.check_name(attr, sym::main) - && !self.sess.check_name(attr, sym::start) - }) - .chain(iter::once(allow_dead_code)) - .collect(); - - ast::Item { id, ident, attrs, kind, vis, span, tokens } - }), - EntryPointType::None | EntryPointType::OtherMain => item, - }; - - smallvec![item] + smallvec![strip_start_attr(self.sess, self.def_site, item)] } } @@ -220,7 +199,7 @@ fn generate_test_harness( let expn_id = ext_cx.resolver.expansion_for_ast_pass( DUMMY_SP, AstPass::TestHarness, - &[sym::main, sym::test, sym::rustc_attrs], + &[sym::rustc_main, sym::test, sym::rustc_attrs], None, ); let def_site = DUMMY_SP.with_def_site_ctxt(expn_id); @@ -246,8 +225,8 @@ fn generate_test_harness( /// /// By default this expands to /// -/// ``` -/// #[main] +/// ```rust,ignore (not real code) +/// #![rustc_main(crate::...::main)] /// pub fn main() { /// extern crate test; /// test::test_main_static(&[ @@ -271,9 +250,9 @@ fn generate_test_harness( /// [`TestCtxt::reexport_test_harness_main`] provides a different name for the `main` /// function and [`TestCtxt::test_runner`] provides a path that replaces /// `test::test_main_static`. -fn mk_main(cx: &mut TestCtxt<'_>) -> P { +fn mk_entry_fn(cx: &mut TestCtxt<'_>, c: &mut ast::Crate) { let sp = cx.def_site; - let ecx = &cx.ext_cx; + let ecx = &mut cx.ext_cx; let test_id = Ident::new(sym::test, sp); let runner_name = match cx.panic_strategy { @@ -290,17 +269,14 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { test_runner.span = sp; let test_main_path_expr = ecx.expr_path(test_runner); - let call_test_main = ecx.expr_call(sp, test_main_path_expr, vec![mk_tests_slice(cx, sp)]); + let call_test_main = + ecx.expr_call(sp, test_main_path_expr, vec![mk_tests_slice(ecx, &cx.test_cases, sp)]); let call_test_main = ecx.stmt_expr(call_test_main); // extern crate test let test_extern_stmt = ecx.stmt_item(sp, ecx.item(sp, test_id, vec![], ast::ItemKind::ExternCrate(None))); - // #[main] - let main_meta = ecx.meta_word(sp, sym::main); - let main_attr = ecx.attribute(main_meta); - // pub fn main() { ... } let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![])); @@ -325,7 +301,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { let main = P(ast::Item { ident: main_id, - attrs: vec![main_attr], + attrs: vec![], id: ast::DUMMY_NODE_ID, kind: main, vis: ast::Visibility { span: sp, kind: ast::VisibilityKind::Public, tokens: None }, @@ -335,18 +311,48 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { // Integrate the new item into existing module structures. let main = AstFragment::Items(smallvec![main]); - cx.ext_cx.monotonic_expander().fully_expand_fragment(main).make_items().pop().unwrap() + let main = ecx.monotonic_expander().fully_expand_fragment(main).make_items().pop().unwrap(); + + // #[rustc_main] attr + let main_id_nested_meta = ast::attr::mk_nested_word_item(main_id); + let rustc_main_meta = ecx.meta_list(sp, sym::rustc_main, vec![main_id_nested_meta]); + let rustc_main_attr = ecx.attribute(rustc_main_meta); + c.attrs.push(rustc_main_attr); + c.items.push(main); } -/// Creates a slice containing every test like so: -/// &[&test1, &test2] -fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P { - debug!("building test vector from {} tests", cx.test_cases.len()); +fn ensure_exist_rustc_main_attr(cx: &mut TestCtxt<'_>, attrs: &mut Vec) { + let sp = cx.def_site; let ecx = &cx.ext_cx; + if ecx.sess.contains_name(attrs, sym::rustc_main) { + return; + } + + let any_exe = ecx.sess.crate_types().iter().any(|ty| *ty == CrateType::Executable); + if !any_exe { + return; + } + + if ecx.sess.contains_name(attrs, sym::no_main) { + return; + } + + let crate_main_nested_meta = ast::attr::mk_nested_word_item(Ident::new(sym::main, DUMMY_SP)); + let ignore_nested_meta = ast::attr::mk_nested_word_item(Ident::new(sym::ignore, DUMMY_SP)); + let rustc_main_meta = + ecx.meta_list(sp, sym::rustc_main, vec![crate_main_nested_meta, ignore_nested_meta]); + let rustc_main_attr = ecx.attribute(rustc_main_meta); + attrs.push(rustc_main_attr); +} + +/// Creates a slice containing every test like so: +/// &[&test1, &test2] +fn mk_tests_slice(ecx: &ExtCtxt<'_>, test_cases: &Vec, sp: Span) -> P { + debug!("building test vector from {} tests", test_cases.len()); ecx.expr_vec_slice( sp, - cx.test_cases + test_cases .iter() .map(|test| { ecx.expr_addr_of(test.span, ecx.expr_path(ecx.path(test.span, vec![test.ident]))) diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index dbe1ff083f0db..cd9031b6fa888 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -7,8 +7,8 @@ use std::os::raw::{c_char, c_int}; use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_codegen_ssa::CrateInfo; +use rustc_hir::EntryFn; use rustc_middle::mir::mono::MonoItem; -use rustc_session::config::EntryFnType; use cranelift_jit::{JITBuilder, JITModule}; @@ -102,56 +102,52 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { assert!(tls_backend_config.borrow_mut().replace(backend_config).is_none()) }); - let (main_def_id, entry_ty) = tcx.entry_fn(LOCAL_CRATE).unwrap(); + let EntryFn { local_def_id: main_def_id, is_naked: main_is_naked, .. } = + tcx.entry_fn(LOCAL_CRATE).unwrap(); let instance = Instance::mono(tcx, main_def_id.to_def_id()).polymorphize(tcx); - match entry_ty { - EntryFnType::Main => { - // FIXME set program arguments somehow - - let main_sig = Signature { - params: vec![], - returns: vec![], - call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)), - }; - let main_func_id = jit_module - .declare_function(tcx.symbol_name(instance).name, Linkage::Import, &main_sig) - .unwrap(); - let finalized_main: *const u8 = jit_module.get_finalized_function(main_func_id); - - CURRENT_MODULE.with(|current_module| { - assert!(current_module.borrow_mut().replace(jit_module).is_none()) - }); - - let f: extern "C" fn() = unsafe { ::std::mem::transmute(finalized_main) }; - f(); - std::process::exit(0); - } - EntryFnType::Start => { - let start_sig = Signature { - params: vec![ - AbiParam::new(jit_module.target_config().pointer_type()), - AbiParam::new(jit_module.target_config().pointer_type()), - ], - returns: vec![AbiParam::new( - jit_module.target_config().pointer_type(), /*isize*/ - )], - call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)), - }; - let start_func_id = jit_module - .declare_function(tcx.symbol_name(instance).name, Linkage::Import, &start_sig) - .unwrap(); - let finalized_start: *const u8 = jit_module.get_finalized_function(start_func_id); - - CURRENT_MODULE.with(|current_module| { - assert!(current_module.borrow_mut().replace(jit_module).is_none()) - }); - - let f: extern "C" fn(c_int, *const *const c_char) -> c_int = - unsafe { ::std::mem::transmute(finalized_start) }; - let ret = f(args.len() as c_int, argv.as_ptr()); - std::process::exit(ret); - } + if !main_is_naked { + // FIXME set program arguments somehow + + let main_sig = Signature { + params: vec![], + returns: vec![], + call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)), + }; + let main_func_id = jit_module + .declare_function(tcx.symbol_name(instance).name, Linkage::Import, &main_sig) + .unwrap(); + let finalized_main: *const u8 = jit_module.get_finalized_function(main_func_id); + + CURRENT_MODULE.with(|current_module| { + assert!(current_module.borrow_mut().replace(jit_module).is_none()) + }); + + let f: extern "C" fn() = unsafe { ::std::mem::transmute(finalized_main) }; + f(); + std::process::exit(0); + } else { + let start_sig = Signature { + params: vec![ + AbiParam::new(jit_module.target_config().pointer_type()), + AbiParam::new(jit_module.target_config().pointer_type()), + ], + returns: vec![AbiParam::new(jit_module.target_config().pointer_type() /*isize*/)], + call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)), + }; + let start_func_id = jit_module + .declare_function(tcx.symbol_name(instance).name, Linkage::Import, &start_sig) + .unwrap(); + let finalized_start: *const u8 = jit_module.get_finalized_function(start_func_id); + + CURRENT_MODULE.with(|current_module| { + assert!(current_module.borrow_mut().replace(jit_module).is_none()) + }); + + let f: extern "C" fn(c_int, *const *const c_char) -> c_int = + unsafe { ::std::mem::transmute(finalized_start) }; + let ret = f(args.len() as c_int, argv.as_ptr()); + std::process::exit(ret); } } diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs index a6266f507765f..06ea9791cc3f9 100644 --- a/compiler/rustc_codegen_cranelift/src/main_shim.rs +++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs @@ -1,6 +1,6 @@ use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; +use rustc_hir::EntryFn; use rustc_hir::LangItem; -use rustc_session::config::EntryFnType; use crate::prelude::*; @@ -12,13 +12,7 @@ pub(crate) fn maybe_create_entry_wrapper( unwind_context: &mut UnwindContext<'_>, ) { let (main_def_id, use_start_lang_item) = match tcx.entry_fn(LOCAL_CRATE) { - Some((def_id, entry_ty)) => ( - def_id.to_def_id(), - match entry_ty { - EntryFnType::Main => true, - EntryFnType::Start => false, - }, - ), + Some(EntryFn { local_def_id, is_naked, .. }) => (local_def_id.to_def_id(), !is_naked), None => return, }; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index e157a38aa03d5..17802dd69c6b8 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -343,8 +343,8 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { if self.sess().opts.optimize != config::OptLevel::No { spflags |= DISPFlags::SPFlagOptimized; } - if let Some((id, _)) = self.tcx.entry_fn(LOCAL_CRATE) { - if id.to_def_id() == def_id { + if let Some(entry_fn) = self.tcx.entry_fn(LOCAL_CRATE) { + if entry_fn.local_def_id.to_def_id() == def_id { spflags |= DISPFlags::SPFlagMainSubprogram; } } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 318eed76acf2b..0c4882ee248f6 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -17,6 +17,7 @@ use rustc_data_structures::sync::{par_iter, ParallelIterator}; use rustc_hir as hir; use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; +use rustc_hir::EntryFn; use rustc_index::vec::Idx; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::cstore::EncodedMetadata; @@ -28,7 +29,7 @@ use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::cgu_reuse_tracker::CguReuse; -use rustc_session::config::{self, EntryFnType}; +use rustc_session::config; use rustc_session::Session; use rustc_target::abi::{Align, LayoutOf, VariantIdx}; @@ -347,7 +348,7 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, ) -> Option { - let main_def_id = cx.tcx().entry_fn(LOCAL_CRATE).map(|(def_id, _)| def_id)?; + let main_def_id = cx.tcx().entry_fn(LOCAL_CRATE).map(|entry_fn| entry_fn.local_def_id)?; let instance = Instance::mono(cx.tcx(), main_def_id.to_def_id()); if !cx.codegen_unit().contains_item(&MonoItem::Fn(instance)) { @@ -358,8 +359,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let main_llfn = cx.get_fn_addr(instance); - return cx.tcx().entry_fn(LOCAL_CRATE).map(|(_, et)| { - let use_start_lang_item = EntryFnType::Start != et; + return cx.tcx().entry_fn(LOCAL_CRATE).map(|EntryFn { is_naked, .. }| { + let use_start_lang_item = !is_naked; create_entry_fn::(cx, main_llfn, main_def_id, use_start_lang_item) }); diff --git a/compiler/rustc_error_codes/src/error_codes/E0137.md b/compiler/rustc_error_codes/src/error_codes/E0137.md index 0a02913d2364d..d4e19170f3f7b 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0137.md +++ b/compiler/rustc_error_codes/src/error_codes/E0137.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + More than one function was declared with the `#[main]` attribute. Erroneous code example: -```compile_fail,E0137 +```compile_fail #![feature(main)] #[main] @@ -16,7 +18,7 @@ This error indicates that the compiler found multiple functions with the `#[main]` attribute. This is an error because there must be a unique entry point into a Rust program. Example: -``` +```compile_fail #![feature(main)] #[main] diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index cb8b9398283ef..7b73eaac5fcbd 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -561,4 +561,8 @@ impl<'a> ExtCtxt<'a> { pub fn meta_word(&self, sp: Span, w: Symbol) -> ast::MetaItem { attr::mk_word_item(Ident::new(w, sp)) } + + pub fn meta_list(&self, sp: Span, w: Symbol, items: Vec) -> ast::MetaItem { + attr::mk_list_item(Ident::new(w, sp), items) + } } diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 1a91eb600a91b..7721781134a83 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -134,9 +134,6 @@ declare_features! ( /// Allows using the `box $expr` syntax. (active, box_syntax, "1.0.0", Some(49733), None), - /// Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls. - (active, main, "1.0.0", Some(29634), None), - /// Allows using `#[start]` on a function indicating that it is the program entrypoint. (active, start, "1.0.0", Some(29633), None), @@ -648,6 +645,10 @@ declare_features! ( /// Allows `extern "wasm" fn` (active, wasm_abi, "1.53.0", Some(83788), None), + /// Allows using `#![rustc_main(...)]` (an implementation detail of `rustc`, + /// it is not on path for eventual stabilization). + (active, rustc_main, "1.53.0", Some(84060), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 7df9b3f0a7960..e7764b56f6e53 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -421,6 +421,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \ which contains the profiler runtime and will never be stable", ), + gated!(rustc_main, AssumedUsed, template!(List: "path"), experimental!(rustc_main)), // ========================================================================== // Internal attributes, Linkage: diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index de10d88c1d250..5bf06c2a76a28 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -4,8 +4,8 @@ use crate::hir; use rustc_ast as ast; use rustc_ast::NodeId; use rustc_macros::HashStable_Generic; -use rustc_span::hygiene::MacroKind; use rustc_span::Symbol; +use rustc_span::{def_id::LocalDefId, hygiene::MacroKind}; use std::array::IntoIter; use std::fmt::Debug; @@ -627,3 +627,11 @@ impl Res { matches!(self, Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::SelfCtor(..)) } } +#[derive(Clone, PartialEq, Hash, Debug)] +pub struct EntryFn { + pub local_def_id: LocalDefId, + pub is_naked: bool, + pub ignored_local_def_ids: Vec, +} + +impl_stable_hash_via_hash!(EntryFn); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 1051fb8cea279..8b0a3ab50ce9a 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,5 +1,5 @@ // ignore-tidy-filelength -use crate::def::{CtorKind, DefKind, Res}; +use crate::def::{CtorKind, DefKind, EntryFn, Res}; use crate::def_id::DefId; crate use crate::hir_id::HirId; use crate::{itemlikevisit, LangItem}; @@ -669,6 +669,8 @@ pub struct Crate<'hir> { /// Collected attributes from HIR nodes. pub attrs: BTreeMap, + + pub entry_fn_attr: Option, } impl Crate<'hir> { diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 36a30900fb26c..78daee34c5f28 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -34,6 +34,7 @@ pub mod weak_lang_items; #[cfg(test)] mod tests; +pub use def::EntryFn; pub use hir::*; pub use hir_id::*; pub use lang_items::{LangItem, LanguageItems}; diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 01853eab530da..a15ed7d360c8e 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -303,7 +303,7 @@ impl<'tcx> Queries<'tcx> { /// an error. fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) { let def_id = match tcx.entry_fn(LOCAL_CRATE) { - Some((def_id, _)) => def_id, + Some(entry_fn) => entry_fn.local_def_id, _ => return, }; diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs index 501e7d624d2e4..9ab0a110e144f 100644 --- a/compiler/rustc_middle/src/hir/map/collector.rs +++ b/compiler/rustc_middle/src/hir/map/collector.rs @@ -118,6 +118,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { proc_macros: _, trait_map: _, attrs: _, + entry_fn_attr: _, } = *krate; hash_body(&mut hcx, root_mod_def_path_hash, item, &mut hir_body_nodes) diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 6c2468b9ffe0b..bd500470d5cf7 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -88,7 +88,7 @@ impl<'tcx> MonoItem<'tcx> { match *self { MonoItem::Fn(ref instance) => { - let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id); + let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|entry_fn| entry_fn.local_def_id); // If this function isn't inlined or otherwise has an extern // indicator, then we'll be creating a globally shared version. if tcx.codegen_fn_attrs(instance.def_id()).contains_extern_indicator() diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index bac69e282a521..86c93a1918eec 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1192,7 +1192,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 { desc { "looking up the entry function of a crate" } } query plugin_registrar_fn(_: CrateNum) -> Option { diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs index c170858ba85a1..4ed7acdee8dce 100644 --- a/compiler/rustc_middle/src/ty/query/mod.rs +++ b/compiler/rustc_middle/src/ty/query/mod.rs @@ -41,10 +41,11 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId}; use rustc_hir::lang_items::{LangItem, LanguageItems}; +use rustc_hir::EntryFn; use rustc_hir::{Crate, ItemLocalId, TraitCandidate}; use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; use rustc_serialize::opaque; -use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; +use rustc_session::config::{OptLevel, OutputFilenames, SymbolManglingVersion}; use rustc_session::utils::NativeLibKind; use rustc_session::CrateDisambiguator; use rustc_target::spec::PanicStrategy; diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index 1fda71d74bbf5..ddb7443ed43d2 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -187,6 +187,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::lang_items::LangItem; +use rustc_hir::EntryFn; use rustc_index::bit_set::GrowableBitSet; use rustc_middle::mir::interpret::{AllocId, ConstValue}; use rustc_middle::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar}; @@ -197,7 +198,6 @@ use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast}; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable}; use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext}; -use rustc_session::config::EntryFnType; use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP}; use smallvec::SmallVec; use std::iter; @@ -1024,7 +1024,7 @@ struct RootCollector<'a, 'tcx> { tcx: TyCtxt<'tcx>, mode: MonoItemCollectionMode, output: &'a mut Vec>>, - entry_fn: Option<(LocalDefId, EntryFnType)>, + entry_fn: Option, } impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> { @@ -1112,7 +1112,7 @@ impl RootCollector<'_, 'v> { && match self.mode { MonoItemCollectionMode::Eager => true, MonoItemCollectionMode::Lazy => { - self.entry_fn.map(|(id, _)| id) == Some(def_id) + self.entry_fn.as_ref().map(|ef| ef.local_def_id) == Some(def_id) || self.tcx.is_reachable_non_generic(def_id) || self .tcx @@ -1141,7 +1141,7 @@ impl RootCollector<'_, 'v> { /// the user writes their own `start` manually. fn push_extra_entry_roots(&mut self) { let main_def_id = match self.entry_fn { - Some((def_id, EntryFnType::Main)) => def_id, + Some(EntryFn { local_def_id: def_id, is_naked: false, .. }) => def_id, _ => return, }; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index df292b141760d..0bc48dff8918b 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1489,6 +1489,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { sym::path, sym::automatically_derived, sym::start, + // reserved for stablization of `rustc_main` attribute sym::main, ]; diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index c63edf365a1aa..e9563471c5419 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -462,6 +462,7 @@ fn create_and_seed_worklist<'tcx>( access_levels: &privacy::AccessLevels, krate: &hir::Crate<'_>, ) -> (Vec, FxHashMap) { + let entry_fn = tcx.entry_fn(LOCAL_CRATE); let worklist = access_levels .map .iter() @@ -472,8 +473,17 @@ 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)), + entry_fn + .as_ref() + .iter() + .map(|entry_fn| tcx.hir().local_def_id_to_hir_id(entry_fn.local_def_id)), ) + .chain(entry_fn.as_ref().iter().flat_map(|entry_fn| { + entry_fn + .ignored_local_def_ids + .iter() + .map(|&local_def_id| tcx.hir().local_def_id_to_hir_id(local_def_id)) + })) .collect::>(); // Seed implemented trait items diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index e53f821e6daff..dd3e50fa46976 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -1,29 +1,41 @@ -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, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_hir::EntryFn; 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::config::CrateType; use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; +enum EntryFnSource { + RustcMainAttr, + NamedMainFn, + StartAttr, +} +pub enum EntryPointType { + None, + MainNamed, + Start, + OtherMain, // Not an entry point, but some other function named main +} + struct EntryContext<'a, 'tcx> { session: &'a Session, map: Map<'tcx>, - /// The top-level function called `main`. - main_fn: Option<(HirId, Span)>, + /// The entry function, either `main` or with attribute `start`. + entry_fn: Option<(HirId, Span, EntryFnSource)>, - /// The function that has attribute named `main`. - attr_main_fn: Option<(HirId, Span)>, + /// Whether the entry function is marked naked. + is_naked: bool, - /// The function that has the attribute 'start' on it. - start_fn: Option<(HirId, Span)>, + /// Ignored entry functions (usually by test harness generator). + ignored_main_fns: Vec, /// The functions that one might think are `main` but aren't, e.g. /// main functions not defined at the top level. For diagnostics. @@ -50,7 +62,22 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> { } } -fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(LocalDefId, EntryFnType)> { +fn visit_rustc_main_attr(tcx: TyCtxt<'_>, ctxt: &mut EntryContext<'_, '_>) { + if let Some(entry_fn) = &tcx.hir().krate().entry_fn_attr { + let hir_id = tcx.hir().local_def_id_to_hir_id(entry_fn.local_def_id); + + ctxt.entry_fn = Some((hir_id, DUMMY_SP, EntryFnSource::RustcMainAttr)); + ctxt.is_naked = entry_fn.is_naked; + ctxt.ignored_main_fns.extend( + entry_fn + .ignored_local_def_ids + .iter() + .map(|&local_def_id| tcx.hir().local_def_id_to_hir_id(local_def_id)), + ); + } +} + +fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option { assert_eq!(cnum, LOCAL_CRATE); let any_exe = tcx.sess.crate_types().iter().any(|ty| *ty == CrateType::Executable); @@ -67,15 +94,30 @@ 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, + entry_fn: None, + is_naked: false, + ignored_main_fns: Vec::new(), non_main_fns: Vec::new(), }; + visit_rustc_main_attr(tcx, &mut ctxt); + tcx.hir().krate().visit_all_item_likes(&mut ctxt); - configure_main(tcx, &ctxt) + if let Some((hir_id, _, _)) = ctxt.entry_fn { + Some(EntryFn { + local_def_id: tcx.hir().local_def_id(hir_id), + is_naked: ctxt.is_naked, + ignored_local_def_ids: ctxt + .ignored_main_fns + .iter() + .map(|&hir_id| tcx.hir().local_def_id(hir_id)) + .collect(), + }) + } else { + no_main_err(tcx, &ctxt); + None + } } // Beware, this is duplicated in `librustc_builtin_macros/test_harness.rs` @@ -84,8 +126,6 @@ fn entry_point_type(ctxt: &EntryContext<'_, '_>, item: &Item<'_>, at_root: bool) let attrs = ctxt.map.attrs(item.hir_id()); if ctxt.session.contains_name(attrs, sym::start) { EntryPointType::Start - } else if ctxt.session.contains_name(attrs, sym::main) { - EntryPointType::MainAttr } else if item.ident.name == sym::main { if at_root { // This is a top-level function so can be `main`. @@ -111,62 +151,49 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) { if let Some(attr) = ctxt.session.find_by_name(attrs, sym::start) { throw_attr_err(&ctxt.session, attr.span, "start"); } - if let Some(attr) = ctxt.session.find_by_name(attrs, sym::main) { - throw_attr_err(&ctxt.session, attr.span, "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::OtherMain => { ctxt.non_main_fns.push((item.hir_id(), item.span)); } - EntryPointType::MainAttr => { - if ctxt.attr_main_fn.is_none() { - ctxt.attr_main_fn = Some((item.hir_id(), item.span)); - } else { + EntryPointType::MainNamed => { + match ctxt.entry_fn { + None => { + ctxt.entry_fn = Some((item.hir_id(), item.span, EntryFnSource::NamedMainFn)); + ctxt.is_naked = false; + } + Some((_, _, EntryFnSource::RustcMainAttr)) + | Some((_, _, EntryFnSource::StartAttr)) => { + // ignore current named main fn. + } + Some((_, _, EntryFnSource::NamedMainFn)) => { + struct_span_err!(ctxt.session, item.span, E0136, "multiple `main` functions") + .emit(); + } + } + } + EntryPointType::Start => match ctxt.entry_fn { + None | Some((_, _, EntryFnSource::NamedMainFn)) => { + ctxt.entry_fn = Some((item.hir_id(), item.span, EntryFnSource::StartAttr)); + ctxt.is_naked = true; + } + Some((_, previous_span, EntryFnSource::RustcMainAttr)) => { struct_span_err!( ctxt.session, item.span, - E0137, - "multiple functions with a `#[main]` attribute" + E0138, + "multiple crate entry definitions" ) - .span_label(item.span, "additional `#[main]` function") - .span_label(ctxt.attr_main_fn.unwrap().1, "first `#[main]` function") + .span_label(previous_span, "previous `#[rustc_main]` attribute here") + .span_label(item.span, "current `start` function") .emit(); } - } - EntryPointType::Start => { - if ctxt.start_fn.is_none() { - ctxt.start_fn = Some((item.hir_id(), item.span)); - } else { - struct_span_err!(ctxt.session, item.span, E0138, "multiple `start` functions") - .span_label(ctxt.start_fn.unwrap().1, "previous `#[start]` function here") + Some((_, previous_span, EntryFnSource::StartAttr)) => { + struct_span_err!(ctxt.session, item.span, E0138, "multiple crate entry functions") + .span_label(previous_span, "previous `#[start]` function here") .span_label(item.span, "multiple `start` functions") .emit(); } - } - } -} - -fn configure_main( - tcx: TyCtxt<'_>, - visitor: &EntryContext<'_, '_>, -) -> Option<(LocalDefId, EntryFnType)> { - if let Some((hir_id, _)) = visitor.start_fn { - Some((tcx.hir().local_def_id(hir_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)) - } else { - no_main_err(tcx, visitor); - None + }, } } @@ -225,7 +252,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 { tcx.entry_fn(LOCAL_CRATE) } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 3fdd47e1ecb8e..b7dd8875f57aa 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1181,6 +1181,12 @@ impl ResolverAstLowering for Resolver<'_> { def_id } + + fn resolve_ast_path_in_value_ns(&mut self, path: &Path, module_id: DefId) -> Option { + let module = self.get_module(module_id); + let parent_scope = &ParentScope::module(module, self); + self.resolve_ast_path(&path, Namespace::ValueNS, parent_scope, true).ok() + } } impl<'a> Resolver<'a> { @@ -3218,7 +3224,7 @@ impl<'a> Resolver<'a> { }; let module = self.get_module(module_id); let parent_scope = &ParentScope::module(module, self); - let res = self.resolve_ast_path(&path, ns, parent_scope).map_err(|_| ())?; + let res = self.resolve_ast_path(&path, ns, parent_scope, false).map_err(|_| ())?; Ok((path, res)) } @@ -3228,12 +3234,13 @@ impl<'a> Resolver<'a> { path: &ast::Path, ns: Namespace, parent_scope: &ParentScope<'a>, + record_used: bool, ) -> Result)> { match self.resolve_path( &Segment::from_path(path), Some(ns), parent_scope, - false, + record_used, path.span, CrateLint::No, ) { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 75bd8880b3460..3e94bdfb10298 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -755,15 +755,6 @@ impl DebuggingOptions { } } -// 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, Encodable, Decodable)] pub enum CrateType { Executable, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index ee1d206095e5d..126121549b3fa 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1006,6 +1006,7 @@ symbols! { rustc_layout_scalar_valid_range_start, rustc_legacy_const_generics, rustc_macro_transparency, + rustc_main, rustc_mir, rustc_nonnull_optimization_guaranteed, rustc_object_lifetime_default, diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 892abb5a34465..1c9df8e3d2474 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -9,6 +9,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; +use rustc_hir::EntryFn; use rustc_hir::{def::Res, ItemKind, Node, PathSegment}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; @@ -17,7 +18,6 @@ use rustc_middle::ty::layout::MAX_SIMD_LANES; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::util::{Discr, IntTypeExt, Representability}; use rustc_middle::ty::{self, ParamEnv, RegionKind, ToPredicate, Ty, TyCtxt}; -use rustc_session::config::EntryFnType; use rustc_session::lint::builtin::UNINHABITED_STATIC; use rustc_span::symbol::sym; use rustc_span::{self, MultiSpan, Span}; @@ -327,8 +327,8 @@ pub(super) fn check_fn<'a, 'tcx>( // Check that the main return type implements the termination trait. if let Some(term_id) = tcx.lang_items().termination() { - if let Some((def_id, EntryFnType::Main)) = tcx.entry_fn(LOCAL_CRATE) { - let main_id = hir.local_def_id_to_hir_id(def_id); + if let Some(EntryFn { local_def_id, is_naked: false, .. }) = tcx.entry_fn(LOCAL_CRATE) { + let main_id = hir.local_def_id_to_hir_id(local_def_id); if main_id == fn_id { let substs = tcx.mk_substs_trait(declared_ret_ty, &[]); let trait_ref = ty::TraitRef::new(term_id, substs); diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 190744fe6f1d8..757e8a2987f85 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -105,7 +105,6 @@ use rustc_middle::middle; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::util; -use rustc_session::config::EntryFnType; use rustc_span::{symbol::sym, Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; @@ -352,10 +351,12 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: LocalDefId) { } fn check_for_entry_fn(tcx: TyCtxt<'_>) { - match tcx.entry_fn(LOCAL_CRATE) { - Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id), - Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id), - _ => {} + if let Some(entry_fn) = tcx.entry_fn(LOCAL_CRATE) { + if !entry_fn.is_naked { + check_main_fn_ty(tcx, entry_fn.local_def_id); + } else { + check_start_fn_ty(tcx, entry_fn.local_def_id); + } } } diff --git a/src/test/ui/attr-main-2.rs b/src/test/ui/attr-main-2.rs deleted file mode 100644 index 3a51f83ba3b18..0000000000000 --- a/src/test/ui/attr-main-2.rs +++ /dev/null @@ -1,11 +0,0 @@ -// run-pass - -#![feature(main)] - -pub fn main() { - panic!() -} - -#[main] -fn foo() { -} diff --git a/src/test/ui/attr-main.rs b/src/test/ui/attr-main.rs deleted file mode 100644 index 9c4caaa4a42eb..0000000000000 --- a/src/test/ui/attr-main.rs +++ /dev/null @@ -1,8 +0,0 @@ -// run-pass -// pretty-expanded FIXME #23616 - -#![feature(main)] - -#[main] -fn foo() { -} diff --git a/src/test/ui/attr.rs b/src/test/ui/attr.rs deleted file mode 100644 index 9c4caaa4a42eb..0000000000000 --- a/src/test/ui/attr.rs +++ /dev/null @@ -1,8 +0,0 @@ -// run-pass -// pretty-expanded FIXME #23616 - -#![feature(main)] - -#[main] -fn foo() { -} diff --git a/src/test/ui/error-codes/E0137.rs b/src/test/ui/error-codes/E0137.rs deleted file mode 100644 index b8299c71bdf6d..0000000000000 --- a/src/test/ui/error-codes/E0137.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(main)] - -#[main] -fn foo() {} - -#[main] -fn f() {} -//~^ ERROR E0137 diff --git a/src/test/ui/error-codes/E0137.stderr b/src/test/ui/error-codes/E0137.stderr deleted file mode 100644 index f4d5e10369ac7..0000000000000 --- a/src/test/ui/error-codes/E0137.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0137]: multiple functions with a `#[main]` attribute - --> $DIR/E0137.rs:7:1 - | -LL | fn foo() {} - | ----------- first `#[main]` function -... -LL | fn f() {} - | ^^^^^^^^^ additional `#[main]` function - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0137`. diff --git a/src/test/ui/error-codes/E0138.stderr b/src/test/ui/error-codes/E0138.stderr index 2dc6976fe0e9c..b2c33cf1ecbea 100644 --- a/src/test/ui/error-codes/E0138.stderr +++ b/src/test/ui/error-codes/E0138.stderr @@ -1,4 +1,4 @@ -error[E0138]: multiple `start` functions +error[E0138]: multiple crate entry functions --> $DIR/E0138.rs:7:1 | LL | fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } diff --git a/src/test/ui/feature-gates/feature-gate-main.rs b/src/test/ui/feature-gates/feature-gate-main.rs deleted file mode 100644 index 9c304a1792fc2..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-main.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[main] -fn foo() {} //~ ERROR: declaration of a non-standard `#[main]` function may change over time diff --git a/src/test/ui/feature-gates/feature-gate-main.stderr b/src/test/ui/feature-gates/feature-gate-main.stderr deleted file mode 100644 index f0ef3b38c6209..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-main.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: declaration of a non-standard `#[main]` function may change over time, for now a top-level `fn main()` is required - --> $DIR/feature-gate-main.rs:2:1 - | -LL | fn foo() {} - | ^^^^^^^^^^^ - | - = note: see issue #29634 for more information - = help: add `#![feature(main)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs index c985298a30aed..6a24a2f7b3d2d 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs +++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs @@ -1,5 +1,4 @@ // Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate. - #![feature(decl_macro)] mod rustc { pub macro unknown() {} } diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr index 1517a7a5c731a..d833214bce6f5 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr +++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr @@ -1,41 +1,41 @@ error: attributes starting with `rustc` are reserved for use by the `rustc` compiler - --> $DIR/feature-gate-rustc-attrs.rs:8:3 + --> $DIR/feature-gate-rustc-attrs.rs:7:3 | LL | #[rustc::unknown] | ^^^^^ error: expected attribute, found macro `rustc::unknown` - --> $DIR/feature-gate-rustc-attrs.rs:8:3 + --> $DIR/feature-gate-rustc-attrs.rs:7:3 | LL | #[rustc::unknown] | ^^^^^^^^^^^^^^ not an attribute error: attributes starting with `rustc` are reserved for use by the `rustc` compiler - --> $DIR/feature-gate-rustc-attrs.rs:13:12 + --> $DIR/feature-gate-rustc-attrs.rs:12:12 | LL | #[unknown::rustc] | ^^^^^ error: expected attribute, found macro `unknown::rustc` - --> $DIR/feature-gate-rustc-attrs.rs:13:3 + --> $DIR/feature-gate-rustc-attrs.rs:12:3 | LL | #[unknown::rustc] | ^^^^^^^^^^^^^^ not an attribute error: attributes starting with `rustc` are reserved for use by the `rustc` compiler - --> $DIR/feature-gate-rustc-attrs.rs:20:3 + --> $DIR/feature-gate-rustc-attrs.rs:19:3 | LL | #[rustc_unknown] | ^^^^^^^^^^^^^ error: cannot find attribute `rustc_unknown` in this scope - --> $DIR/feature-gate-rustc-attrs.rs:20:3 + --> $DIR/feature-gate-rustc-attrs.rs:19:3 | LL | #[rustc_unknown] | ^^^^^^^^^^^^^ error[E0658]: the `#[rustc_dummy]` attribute is just used for rustc unit tests and will never be stable - --> $DIR/feature-gate-rustc-attrs.rs:18:1 + --> $DIR/feature-gate-rustc-attrs.rs:17:1 | LL | #[rustc_dummy] | ^^^^^^^^^^^^^^ diff --git a/src/test/ui/feature-gates/feature-gate-rustc_main.rs b/src/test/ui/feature-gates/feature-gate-rustc_main.rs new file mode 100644 index 0000000000000..a333894a80eb4 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-rustc_main.rs @@ -0,0 +1,2 @@ +#![rustc_main(foo)] //~ ERROR: the `#[rustc_main]` attribute is an experimental feature +fn foo() {} diff --git a/src/test/ui/feature-gates/feature-gate-rustc_main.stderr b/src/test/ui/feature-gates/feature-gate-rustc_main.stderr new file mode 100644 index 0000000000000..e58ff5d5dda46 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-rustc_main.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[rustc_main]` attribute is an experimental feature + --> $DIR/feature-gate-rustc_main.rs:1:1 + | +LL | #![rustc_main(foo)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #84060 for more information + = help: add `#![feature(rustc_main)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs index 07167fa695e41..ba535f8d91873 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs @@ -106,24 +106,6 @@ mod export_name { //~| NOTE not a function or static } -#[main] -//~^ ERROR: `main` attribute can only be used on functions -mod main { - mod inner { #![main] } - //~^ ERROR: `main` attribute can only be used on functions - - // for `fn f()` case, see feature-gate-main.rs - - #[main] struct S; - //~^ ERROR: `main` attribute can only be used on functions - - #[main] type T = S; - //~^ ERROR: `main` attribute can only be used on functions - - #[main] impl S { } - //~^ ERROR: `main` attribute can only be used on functions -} - #[start] //~^ ERROR: `start` attribute can only be used on functions mod start { diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index 33a5021cde430..5a1b340ac2a65 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -8,62 +8,32 @@ LL | #[inline = "2100"] fn f() { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #57571 -error: `main` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:109:1 - | -LL | #[main] - | ^^^^^^^ - -error: `main` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:112:17 - | -LL | mod inner { #![main] } - | ^^^^^^^^ - -error: `main` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:117:5 - | -LL | #[main] struct S; - | ^^^^^^^ - -error: `main` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:120:5 - | -LL | #[main] type T = S; - | ^^^^^^^ - -error: `main` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:123:5 - | -LL | #[main] impl S { } - | ^^^^^^^ - error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:127:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:109:1 | LL | #[start] | ^^^^^^^^ error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:130:17 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:112:17 | LL | mod inner { #![start] } | ^^^^^^^^^ error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:135:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:117:5 | LL | #[start] struct S; | ^^^^^^^^ error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:138:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:120:5 | LL | #[start] type T = S; | ^^^^^^^^ error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:141:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:123:5 | LL | #[start] impl S { } | ^^^^^^^^ @@ -245,6 +215,6 @@ error: attribute should be applied to a function or static LL | #[export_name = "2200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a function or static -error: aborting due to 36 previous errors +error: aborting due to 31 previous errors For more information about this error, try `rustc --explain E0518`. diff --git a/src/test/ui/intrinsics/intrinsic-alignment.rs b/src/test/ui/intrinsics/intrinsic-alignment.rs index 2bf40db5ad290..18b76406783b1 100644 --- a/src/test/ui/intrinsics/intrinsic-alignment.rs +++ b/src/test/ui/intrinsics/intrinsic-alignment.rs @@ -1,7 +1,8 @@ // run-pass // ignore-wasm32-bare seems not important to test here -#![feature(intrinsics, main)] +#![feature(intrinsics, rustc_main)] +#![rustc_main(m::main)] mod rusti { extern "rust-intrinsic" { @@ -21,7 +22,6 @@ mod rusti { target_os = "solaris", target_os = "vxworks"))] mod m { - #[main] #[cfg(target_arch = "x86")] pub fn main() { unsafe { @@ -30,7 +30,6 @@ mod m { } } - #[main] #[cfg(not(target_arch = "x86"))] pub fn main() { unsafe { @@ -42,7 +41,6 @@ mod m { #[cfg(target_env = "sgx")] mod m { - #[main] #[cfg(target_arch = "x86_64")] pub fn main() { unsafe { @@ -54,7 +52,6 @@ mod m { #[cfg(target_os = "windows")] mod m { - #[main] pub fn main() { unsafe { assert_eq!(::rusti::pref_align_of::(), 8); diff --git a/src/test/ui/lint/dead-code/lint-dead-code-2.rs b/src/test/ui/lint/dead-code/lint-dead-code-2.rs index 88db4f88c3feb..12f109e798e33 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-2.rs +++ b/src/test/ui/lint/dead-code/lint-dead-code-2.rs @@ -1,6 +1,6 @@ #![allow(unused_variables)] #![deny(dead_code)] -#![feature(main, start)] +#![feature(start)] struct Foo; @@ -21,9 +21,6 @@ fn live_fn() {} fn dead_fn() {} //~ ERROR: function is never used -#[main] -fn dead_fn2() {} //~ ERROR: function is never used - fn used_fn() {} #[start] @@ -37,5 +34,4 @@ fn start(_: isize, _: *const *const u8) -> isize { // this is not main fn main() { //~ ERROR: function is never used dead_fn(); - dead_fn2(); } diff --git a/src/test/ui/lint/dead-code/lint-dead-code-2.stderr b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr index b01ba57f98580..1f0865f47b6a5 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-2.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr @@ -10,17 +10,11 @@ note: the lint level is defined here LL | #![deny(dead_code)] | ^^^^^^^^^ -error: function is never used: `dead_fn2` - --> $DIR/lint-dead-code-2.rs:25:4 - | -LL | fn dead_fn2() {} - | ^^^^^^^^ - error: function is never used: `main` - --> $DIR/lint-dead-code-2.rs:38:4 + --> $DIR/lint-dead-code-2.rs:35:4 | LL | fn main() { | ^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/main-wrong-location.rs b/src/test/ui/main-wrong-location.rs index f75d08813cdcd..f3acd80a7a48f 100644 --- a/src/test/ui/main-wrong-location.rs +++ b/src/test/ui/main-wrong-location.rs @@ -1,6 +1,6 @@ mod m { //~^ ERROR `main` function not found - // An inferred main entry point (that doesn't use #[main]) + // An inferred main entry point // must appear at the top of the crate fn main() { } } diff --git a/src/test/ui/main-wrong-location.stderr b/src/test/ui/main-wrong-location.stderr index e301c2ff09ad7..6d2ded05b5f19 100644 --- a/src/test/ui/main-wrong-location.stderr +++ b/src/test/ui/main-wrong-location.stderr @@ -3,7 +3,7 @@ error[E0601]: `main` function not found in crate `main_wrong_location` | LL | / mod m { LL | | -LL | | // An inferred main entry point (that doesn't use #[main]) +LL | | // An inferred main entry point LL | | // must appear at the top of the crate LL | | fn main() { } LL | | } diff --git a/src/test/ui/multiple-main-2.rs b/src/test/ui/multiple-main-2.rs deleted file mode 100644 index e4685b1e00456..0000000000000 --- a/src/test/ui/multiple-main-2.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(main)] - -#[main] -fn bar() { -} - -#[main] -fn foo() { //~ ERROR multiple functions with a `#[main]` attribute -} diff --git a/src/test/ui/multiple-main-2.stderr b/src/test/ui/multiple-main-2.stderr deleted file mode 100644 index 24bc9a8878b08..0000000000000 --- a/src/test/ui/multiple-main-2.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0137]: multiple functions with a `#[main]` attribute - --> $DIR/multiple-main-2.rs:8:1 - | -LL | / fn bar() { -LL | | } - | |_- first `#[main]` function -... -LL | / fn foo() { -LL | | } - | |_^ additional `#[main]` function - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0137`. diff --git a/src/test/ui/multiple-main-3.rs b/src/test/ui/multiple-main-3.rs deleted file mode 100644 index d1b5ae9a83315..0000000000000 --- a/src/test/ui/multiple-main-3.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![feature(main)] - -#[main] -fn main1() { -} - -mod foo { - #[main] - fn main2() { //~ ERROR multiple functions with a `#[main]` attribute - } -} diff --git a/src/test/ui/multiple-main-3.stderr b/src/test/ui/multiple-main-3.stderr deleted file mode 100644 index ec171b76a284a..0000000000000 --- a/src/test/ui/multiple-main-3.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0137]: multiple functions with a `#[main]` attribute - --> $DIR/multiple-main-3.rs:9:5 - | -LL | / fn main1() { -LL | | } - | |_- first `#[main]` function -... -LL | / fn main2() { -LL | | } - | |_____^ additional `#[main]` function - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0137`. diff --git a/src/test/ui/rfc-1260/rustc_main_with_invalid_path.rs b/src/test/ui/rfc-1260/rustc_main_with_invalid_path.rs new file mode 100644 index 0000000000000..a6e081fd3771c --- /dev/null +++ b/src/test/ui/rfc-1260/rustc_main_with_invalid_path.rs @@ -0,0 +1,4 @@ +#![feature(rustc_main)] +//~^ ERROR `main` function not found +#![rustc_main(alt_main)] +//~^ ERROR #[rustc_main] resolution failure diff --git a/src/test/ui/rfc-1260/rustc_main_with_invalid_path.stderr b/src/test/ui/rfc-1260/rustc_main_with_invalid_path.stderr new file mode 100644 index 0000000000000..5410af1c31655 --- /dev/null +++ b/src/test/ui/rfc-1260/rustc_main_with_invalid_path.stderr @@ -0,0 +1,17 @@ +error: #[rustc_main] resolution failure + --> $DIR/rustc_main_with_invalid_path.rs:3:1 + | +LL | #![rustc_main(alt_main)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0601]: `main` function not found in crate `rustc_main_with_invalid_path` + --> $DIR/rustc_main_with_invalid_path.rs:1:1 + | +LL | / #![feature(rustc_main)] +LL | | +LL | | #![rustc_main(alt_main)] + | |________________________^ consider adding a `main` function to `$DIR/rustc_main_with_invalid_path.rs` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/rfc-1260/rustc_main_with_path.rs b/src/test/ui/rfc-1260/rustc_main_with_path.rs new file mode 100644 index 0000000000000..21d0e653988d3 --- /dev/null +++ b/src/test/ui/rfc-1260/rustc_main_with_path.rs @@ -0,0 +1,7 @@ +// run-pass +#![feature(rustc_main)] +#![rustc_main(crate::inner::alt_main)] + +mod inner { + fn alt_main() {} +} diff --git a/src/test/ui/rfc-1260/rustc_main_with_path_naked.rs b/src/test/ui/rfc-1260/rustc_main_with_path_naked.rs new file mode 100644 index 0000000000000..a24bfd7b32960 --- /dev/null +++ b/src/test/ui/rfc-1260/rustc_main_with_path_naked.rs @@ -0,0 +1,7 @@ +// run-pass +#![feature(rustc_main)] +#![rustc_main(crate::inner::alt_main, naked)] + +mod inner { + fn alt_main(_: isize, _: *const *const u8) -> isize { 0 } +} diff --git a/src/test/ui/test-attrs/test-main-not-dead-attr.rs b/src/test/ui/test-attrs/test-main-not-dead-attr.rs deleted file mode 100644 index 628b1896ace4f..0000000000000 --- a/src/test/ui/test-attrs/test-main-not-dead-attr.rs +++ /dev/null @@ -1,9 +0,0 @@ -// run-pass -// compile-flags: --test - -#![feature(main)] - -#![deny(dead_code)] - -#[main] -fn foo() { panic!(); } diff --git a/src/test/ui/test-attrs/test-runner-hides-buried-main.rs b/src/test/ui/test-attrs/test-runner-hides-buried-main.rs index bf5482056d4b4..cb58961d7b087 100644 --- a/src/test/ui/test-attrs/test-runner-hides-buried-main.rs +++ b/src/test/ui/test-attrs/test-runner-hides-buried-main.rs @@ -1,15 +1,11 @@ // run-pass // compile-flags: --test -#![feature(main)] +#![feature(rustc_main)] +#![rustc_main(a::c)] #![allow(dead_code)] mod a { - fn b() { - (|| { - #[main] - fn c() { panic!(); } - })(); - } + fn c() { panic!(); } } diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index c847712ec2e9e..4c83494ec1d13 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -584,7 +584,7 @@ pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option, def_id: DefId) -> bool { cx.tcx .entry_fn(LOCAL_CRATE) - .map_or(false, |(entry_fn_def_id, _)| def_id == entry_fn_def_id.to_def_id()) + .map_or(false, |entry_fn| def_id == entry_fn.local_def_id.to_def_id()) } /// Returns `true` if the expression is in the program's `#[panic_handler]`. diff --git a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs index 995787c533668..5fc6afad3144a 100644 --- a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs +++ b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs @@ -1,11 +1,11 @@ // ignore-macos // ignore-windows -#![feature(main)] +#![feature(rustc_main)] +#![rustc_main(a)] #[warn(clippy::main_recursion)] #[allow(unconditional_recursion)] -#[main] fn a() { println!("Hello, World!"); a();