1
Fork 0

remove support for the #[start] attribute

This commit is contained in:
Ralf Jung 2024-12-14 09:13:12 +01:00
parent 341f60327f
commit 56c90dc31e
176 changed files with 454 additions and 1260 deletions

View file

@ -18,12 +18,6 @@ pub enum EntryPointType {
/// fn main() {}
/// ```
RustcMainAttr,
/// This is a function with the `#[start]` attribute.
/// ```ignore (clashes with test entrypoint)
/// #[start]
/// fn main() {}
/// ```
Start,
/// This function is **not** an entrypoint but simply named `main` (not at the root).
/// This is only used for diagnostics.
/// ```
@ -40,9 +34,7 @@ pub fn entry_point_type(
at_root: bool,
name: Option<Symbol>,
) -> EntryPointType {
if attr::contains_name(attrs, sym::start) {
EntryPointType::Start
} else if attr::contains_name(attrs, sym::rustc_main) {
if attr::contains_name(attrs, sym::rustc_main) {
EntryPointType::RustcMainAttr
} else if let Some(name) = name
&& name == sym::main

View file

@ -230,18 +230,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}
ast::ItemKind::Fn(..) => {
if attr::contains_name(&i.attrs, sym::start) {
gate!(
&self,
start,
i.span,
"`#[start]` functions are experimental and their signature may change \
over time"
);
}
}
ast::ItemKind::Struct(..) | ast::ItemKind::Enum(..) | ast::ItemKind::Union(..) => {
for attr in attr::filter_by_name(&i.attrs, sym::repr) {
for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {

View file

@ -204,11 +204,11 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
ast::mut_visit::walk_item(self, item);
self.depth -= 1;
// Remove any #[rustc_main] or #[start] from the AST so it doesn't
// Remove any #[rustc_main] 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.
match entry_point_type(&item, self.depth == 0) {
EntryPointType::MainNamed | EntryPointType::RustcMainAttr | EntryPointType::Start => {
EntryPointType::MainNamed | EntryPointType::RustcMainAttr => {
let allow_dead_code = attr::mk_attr_nested_word(
&self.sess.psess.attr_id_generator,
ast::AttrStyle::Outer,
@ -217,8 +217,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
sym::dead_code,
self.def_site,
);
item.attrs
.retain(|attr| !attr.has_name(sym::rustc_main) && !attr.has_name(sym::start));
item.attrs.retain(|attr| !attr.has_name(sym::rustc_main));
item.attrs.push(allow_dead_code);
}
EntryPointType::None | EntryPointType::OtherMain => {}

View file

@ -1,7 +1,7 @@
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
use rustc_hir::LangItem;
use rustc_middle::ty::{AssocKind, GenericArg};
use rustc_session::config::{EntryFnType, sigpipe};
use rustc_session::config::EntryFnType;
use rustc_span::{DUMMY_SP, Ident};
use crate::prelude::*;
@ -14,10 +14,9 @@ pub(crate) fn maybe_create_entry_wrapper(
is_jit: bool,
is_primary_cgu: bool,
) {
let (main_def_id, (is_main_fn, sigpipe)) = match tcx.entry_fn(()) {
let (main_def_id, sigpipe) = match tcx.entry_fn(()) {
Some((def_id, entry_ty)) => (def_id, match entry_ty {
EntryFnType::Main { sigpipe } => (true, sigpipe),
EntryFnType::Start => (false, sigpipe::DEFAULT),
EntryFnType::Main { sigpipe } => sigpipe,
}),
None => return,
};
@ -31,14 +30,13 @@ pub(crate) fn maybe_create_entry_wrapper(
return;
}
create_entry_fn(tcx, module, main_def_id, is_jit, is_main_fn, sigpipe);
create_entry_fn(tcx, module, main_def_id, is_jit, sigpipe);
fn create_entry_fn(
tcx: TyCtxt<'_>,
m: &mut dyn Module,
rust_main_def_id: DefId,
ignore_lang_start_wrapper: bool,
is_main_fn: bool,
sigpipe: u8,
) {
let main_ret_ty = tcx.fn_sig(rust_main_def_id).no_bound_vars().unwrap().output();
@ -94,8 +92,8 @@ pub(crate) fn maybe_create_entry_wrapper(
let main_func_ref = m.declare_func_in_func(main_func_id, &mut bcx.func);
let result = if is_main_fn && ignore_lang_start_wrapper {
// regular main fn, but ignoring #[lang = "start"] as we are running in the jit
let result = if ignore_lang_start_wrapper {
// ignoring #[lang = "start"] as we are running in the jit
// FIXME set program arguments somehow
let call_inst = bcx.ins().call(main_func_ref, &[]);
let call_results = bcx.func.dfg.inst_results(call_inst).to_owned();
@ -133,7 +131,8 @@ pub(crate) fn maybe_create_entry_wrapper(
types::I64 => bcx.ins().sextend(types::I64, res),
_ => unimplemented!("16bit systems are not yet supported"),
}
} else if is_main_fn {
} else {
// Regular main fn invoked via start lang item.
let start_def_id = tcx.require_lang_item(LangItem::Start, None);
let start_instance = Instance::expect_resolve(
tcx,
@ -150,10 +149,6 @@ pub(crate) fn maybe_create_entry_wrapper(
let call_inst =
bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv, arg_sigpipe]);
bcx.inst_results(call_inst)[0]
} else {
// using user-defined start fn
let call_inst = bcx.ins().call(main_func_ref, &[arg_argc, arg_argv]);
bcx.inst_results(call_inst)[0]
};
bcx.ins().return_(&[result]);

View file

@ -426,19 +426,6 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> {
run_command_with_env(&command, None, Some(env))?;
maybe_run_command_in_vm(&[&cargo_target_dir.join("track-caller-attribute")], env, args)?;
// FIXME: create a function "display_if_not_quiet" or something along the line.
println!("[AOT] mod_bench");
let mut command = args.config_info.rustc_command_vec();
command.extend_from_slice(&[
&"example/mod_bench.rs",
&"--crate-type",
&"bin",
&"--target",
&args.config_info.target_triple,
]);
run_command_with_env(&command, None, Some(env))?;
// FIXME: the compiled binary is not run.
Ok(())
}
@ -696,19 +683,6 @@ fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> {
Ok(())
}
// echo "[BENCH COMPILE] mod_bench"
//
// COMPILE_MOD_BENCH_INLINE="$RUSTC example/mod_bench.rs --crate-type bin -Zmir-opt-level=3 -O --crate-name mod_bench_inline"
// COMPILE_MOD_BENCH_LLVM_0="rustc example/mod_bench.rs --crate-type bin -Copt-level=0 -o $cargo_target_dir/mod_bench_llvm_0 -Cpanic=abort"
// COMPILE_MOD_BENCH_LLVM_1="rustc example/mod_bench.rs --crate-type bin -Copt-level=1 -o $cargo_target_dir/mod_bench_llvm_1 -Cpanic=abort"
// COMPILE_MOD_BENCH_LLVM_2="rustc example/mod_bench.rs --crate-type bin -Copt-level=2 -o $cargo_target_dir/mod_bench_llvm_2 -Cpanic=abort"
// COMPILE_MOD_BENCH_LLVM_3="rustc example/mod_bench.rs --crate-type bin -Copt-level=3 -o $cargo_target_dir/mod_bench_llvm_3 -Cpanic=abort"
//
// Use 100 runs, because a single compilations doesn't take more than ~150ms, so it isn't very slow
// hyperfine --runs ${COMPILE_RUNS:-100} "$COMPILE_MOD_BENCH_INLINE" "$COMPILE_MOD_BENCH_LLVM_0" "$COMPILE_MOD_BENCH_LLVM_1" "$COMPILE_MOD_BENCH_LLVM_2" "$COMPILE_MOD_BENCH_LLVM_3"
// echo "[BENCH RUN] mod_bench"
// hyperfine --runs ${RUN_RUNS:-10} $cargo_target_dir/mod_bench{,_inline} $cargo_target_dir/mod_bench_llvm_*
fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> {
if !args.is_using_gcc_master_branch() {
println!("Not using GCC master branch. Skipping `extended_rand_tests`.");

View file

@ -1,5 +1,6 @@
#![feature(start, core_intrinsics, alloc_error_handler, lang_items)]
#![feature(core_intrinsics, alloc_error_handler, lang_items)]
#![no_std]
#![no_main]
#![allow(internal_features)]
extern crate alloc;
@ -37,8 +38,8 @@ unsafe extern "C" fn _Unwind_Resume() {
core::intrinsics::unreachable();
}
#[start]
fn main(_argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int {
let world: Box<&str> = Box::new("Hello World!\0");
unsafe {
puts(*world as *const str as *const u8);

View file

@ -1,7 +1,7 @@
// Adapted from https://github.com/sunfishcode/mir2cranelift/blob/master/rust-examples/nocore-hello-world.rs
#![feature(
no_core, unboxed_closures, start, lang_items, never_type, linkage,
no_core, unboxed_closures, lang_items, never_type, linkage,
extern_types, thread_local
)]
#![no_core]

View file

@ -1,36 +0,0 @@
#![feature(start, core_intrinsics, lang_items)]
#![no_std]
#![allow(internal_features)]
#[link(name = "c")]
extern "C" {}
#[panic_handler]
fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! {
core::intrinsics::abort();
}
#[lang="eh_personality"]
fn eh_personality(){}
// Required for rustc_codegen_llvm
#[no_mangle]
unsafe extern "C" fn _Unwind_Resume() {
core::intrinsics::unreachable();
}
#[start]
fn main(_argc: isize, _argv: *const *const u8) -> isize {
for i in 2..100_000_000 {
black_box((i + 1) % i);
}
0
}
#[inline(never)]
fn black_box(i: u32) {
if i != 1 {
core::intrinsics::abort();
}
}

View file

@ -513,7 +513,6 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
} else {
// If the symbol already exists, it is an error: for example, the user wrote
// #[no_mangle] extern "C" fn main(..) {..}
// instead of #[start]
None
}
}

View file

@ -3,11 +3,12 @@
// Run-time:
// status: signal
#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)]
#![allow(internal_features)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
@ -49,7 +50,7 @@ fn test_fail() -> ! {
unsafe { intrinsics::abort() };
}
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
test_fail();
}

View file

@ -3,11 +3,12 @@
// Run-time:
// status: signal
#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)]
#![allow(internal_features)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
@ -50,8 +51,8 @@ fn fail() -> i32 {
0
}
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
fail();
0
}

View file

@ -7,10 +7,11 @@
// 5
// 10
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
@ -28,8 +29,8 @@ fn make_array() -> [u8; 3] {
[42, 10, 5]
}
#[start]
fn main(argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
let array = [42, 7, 5];
let array2 = make_array();
unsafe {

View file

@ -6,10 +6,11 @@
// 10
#![allow(internal_features, unused_attributes)]
#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs, track_caller)]
#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs, track_caller)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
@ -142,8 +143,8 @@ fn inc(num: isize) -> isize {
}
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
argc = inc(argc);
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc);

View file

@ -8,10 +8,11 @@
// Int argument: 2
// Both args: 11
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
@ -22,8 +23,8 @@ mod libc {
}
}
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
let string = "Arg: %d\n\0";
let mut closure = || {
unsafe {

View file

@ -5,10 +5,11 @@
// stdout: true
// 1
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
@ -19,8 +20,8 @@ mod libc {
}
}
#[start]
fn main(argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
unsafe {
if argc == 1 {
libc::printf(b"true\n\0" as *const u8 as *const i8);

View file

@ -3,11 +3,12 @@
// Run-time:
// status: 0
#![feature(auto_traits, lang_items, no_core, start)]
#![feature(auto_traits, lang_items, no_core)]
#![allow(internal_features)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
@ -34,7 +35,7 @@ pub(crate) unsafe auto trait Freeze {}
* Code
*/
#[start]
fn main(_argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
0
}

View file

@ -3,11 +3,12 @@
// Run-time:
// status: 2
#![feature(auto_traits, lang_items, no_core, start, intrinsics)]
#![feature(auto_traits, lang_items, no_core, intrinsics)]
#![allow(internal_features)]
#![no_std]
#![no_core]
#![no_main]
mod libc {
#[link(name = "c")]
@ -41,8 +42,8 @@ pub(crate) unsafe auto trait Freeze {}
* Code
*/
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
unsafe {
libc::exit(2);
}

View file

@ -3,11 +3,12 @@
// Run-time:
// status: 1
#![feature(auto_traits, lang_items, no_core, start)]
#![feature(auto_traits, lang_items, no_core)]
#![allow(internal_features)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
@ -34,7 +35,7 @@ pub(crate) unsafe auto trait Freeze {}
* Code
*/
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
1
}

View file

@ -4,10 +4,11 @@
// status: 0
// stdout: 1
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
@ -26,8 +27,8 @@ fn call_func(func: fn(i16) -> i8, param: i16) -> i8 {
func(param)
}
#[start]
fn main(argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
unsafe {
let result = call_func(i16_as_i8, argc as i16) as isize;
libc::printf(b"%ld\n\0" as *const u8 as *const i8, result);

View file

@ -8,10 +8,11 @@
// 11
#![allow(internal_features, unused_attributes)]
#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs, track_caller)]
#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs, track_caller)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
@ -148,8 +149,8 @@ fn update_num(num: &mut isize) {
*num = *num + 5;
}
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
let mut test = test(argc);
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field);

View file

@ -6,10 +6,11 @@
// 10
#![allow(internal_features, unused_attributes)]
#![feature(auto_traits, lang_items, no_core, start, intrinsics, arbitrary_self_types, rustc_attrs)]
#![feature(auto_traits, lang_items, no_core, intrinsics, arbitrary_self_types, rustc_attrs)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
@ -231,8 +232,8 @@ pub fn panic_const_mul_overflow() -> ! {
* Code
*/
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, 40 + argc);
libc::printf(b"%ld\n\0" as *const u8 as *const i8, 40 - argc);

View file

@ -4,10 +4,11 @@
// status: 0
// stdout: 1
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
@ -24,8 +25,8 @@ fn make_array() -> [u8; 3] {
[42, 10, 5]
}
#[start]
fn main(argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
unsafe {
let ptr = ONE as *mut usize;
let value = ptr as usize;

View file

@ -6,11 +6,12 @@
// 10
// 42
#![feature(auto_traits, lang_items, no_core, start, intrinsics)]
#![feature(auto_traits, lang_items, no_core, intrinsics)]
#![allow(internal_features)]
#![no_std]
#![no_core]
#![no_main]
#[lang = "copy"]
pub unsafe trait Copy {}
@ -61,8 +62,8 @@ fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u3
)
}
#[start]
fn main(argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
let (a, b, c, d, e, f, g, h, i, j) = int_cast(10, 42);
unsafe {
libc::printf(b"%d\n\0" as *const u8 as *const i8, c);

View file

@ -4,10 +4,11 @@
// status: 0
// stdout: 5
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
@ -26,8 +27,8 @@ fn index_slice(s: &[u32]) -> u32 {
}
}
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
let array = [42, 7, 5];
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, index_slice(&array));

View file

@ -9,11 +9,12 @@
// 12
// 1
#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)]
#![allow(internal_features)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
@ -98,8 +99,8 @@ static mut WITH_REF: WithRef = WithRef {
refe: unsafe { &TEST },
};
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, CONSTANT);
libc::printf(b"%ld\n\0" as *const u8 as *const i8, TEST2.field);

View file

@ -5,11 +5,12 @@
// stdout: 1
// 2
#![feature(auto_traits, lang_items, no_core, start, intrinsics)]
#![feature(auto_traits, lang_items, no_core, intrinsics)]
#![allow(internal_features)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
@ -55,8 +56,8 @@ fn one() -> isize {
1
}
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
let test = Test {
field: one(),
};

View file

@ -4,11 +4,12 @@
// status: 0
// stdout: 3
#![feature(auto_traits, lang_items, no_core, start, intrinsics)]
#![feature(auto_traits, lang_items, no_core, intrinsics)]
#![allow(internal_features)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
@ -42,8 +43,8 @@ mod libc {
* Code
*/
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
let test: (isize, isize, isize) = (3, 1, 4);
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.0);

View file

@ -748,7 +748,6 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
} else {
// If the symbol already exists, it is an error: for example, the user wrote
// #[no_mangle] extern "C" fn main(..) {..}
// instead of #[start]
None
}
}

View file

@ -211,7 +211,7 @@ codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but
codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions
codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times
.help = did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead
.help = did you use `#[no_mangle]` on `fn main`? Use `#![no_main]` to suppress the usual Rust-generated entry point
codegen_ssa_no_field = no field `{$name}`

View file

@ -490,8 +490,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let ptr_ty = cx.type_ptr();
let (arg_argc, arg_argv) = get_argc_argv(&mut bx);
let (start_fn, start_ty, args, instance) = if let EntryFnType::Main { sigpipe } = entry_type
{
let EntryFnType::Main { sigpipe } = entry_type;
let (start_fn, start_ty, args, instance) = {
let start_def_id = cx.tcx().require_lang_item(LangItem::Start, None);
let start_instance = ty::Instance::expect_resolve(
cx.tcx(),
@ -512,10 +512,6 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
vec![rust_main, arg_argc, arg_argv, arg_sigpipe],
Some(start_instance),
)
} else {
debug!("using user-defined start fn");
let start_ty = cx.type_func(&[isize_ty, ptr_ty], isize_ty);
(rust_main, start_ty, vec![arg_argc, arg_argv], None)
};
let result = bx.call(start_ty, None, None, start_fn, &args, None, instance);
@ -530,7 +526,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
}
}
/// Obtain the `argc` and `argv` values to pass to the rust start function.
/// Obtain the `argc` and `argv` values to pass to the rust start function
/// (i.e., the "start" lang item).
fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(bx: &mut Bx) -> (Bx::Value, Bx::Value) {
if bx.cx().sess().target.os.contains("uefi") {
// Params for UEFI

View file

@ -1,32 +1,3 @@
#### Note: this error code is no longer emitted by the compiler.
A function with the `start` attribute was declared with type parameters.
Erroneous code example:
```compile_fail,E0132
#![feature(start)]
#[start]
fn f<T>() {}
```
It is not possible to declare type parameters on a function that has the `start`
attribute. Such a function must have the following type signature (for more
information, view [the unstable book][1]):
[1]: https://doc.rust-lang.org/unstable-book/language-features/start.html
```
# let _:
fn(isize, *const *const u8) -> isize;
```
Example:
```
#![feature(start)]
#[start]
fn my_start(argc: isize, argv: *const *const u8) -> isize {
0
}
```

View file

@ -1,25 +1,3 @@
#### Note: this error code is no longer emitted by the compiler.
More than one function was declared with the `#[start]` attribute.
Erroneous code example:
```compile_fail,E0138
#![feature(start)]
#[start]
fn foo(argc: isize, argv: *const *const u8) -> isize {}
#[start]
fn f(argc: isize, argv: *const *const u8) -> isize {}
// error: multiple 'start' functions
```
This error indicates that the compiler found multiple functions with the
`#[start]` attribute. This is an error because there must be a unique entry
point into a Rust program. Example:
```
#![feature(start)]
#[start]
fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok!
```

View file

@ -1,13 +1,3 @@
#### Note: this error code is no longer emitted by the compiler.
The `start` function was defined with a where clause.
Erroneous code example:
```compile_fail,E0647
#![feature(start)]
#[start]
fn start(_: isize, _: *const *const u8) -> isize where (): Copy {
//^ error: `#[start]` function is not allowed to have a where clause
0
}
```

View file

@ -24,6 +24,10 @@
//
// Both columns are necessary because it's not possible in Rust to create a new identifier such as
// `E0123` from an integer literal such as `0123`, unfortunately.
//
// Do *not* remove entries from this list. Instead, just add a note th the corresponding markdown
// file saying that this error is not emitted by the compiler any more (see E0001.md for an
// example), and remove all code examples that do not build any more.
#[macro_export]
macro_rules! error_codes {
($macro:path) => (

View file

@ -448,7 +448,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
),
// Entry point:
ungated!(start, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
ungated!(no_start, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No),
ungated!(no_main, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No),

View file

@ -220,8 +220,9 @@ declare_features! (
(removed, rustc_diagnostic_macros, "1.38.0", None, None),
/// Allows identifying crates that contain sanitizer runtimes.
(removed, sanitizer_runtime, "1.17.0", None, None),
(removed, simd, "1.0.0", Some(27731),
Some("removed in favor of `#[repr(simd)]`")),
(removed, simd, "1.0.0", Some(27731), Some("removed in favor of `#[repr(simd)]`")),
/// Allows using `#[start]` on a function indicating that it is the program entrypoint.
(removed, start, "1.0.0", Some(29633), Some("not portable enough and never RFC'd")),
/// Allows `#[link(kind = "static-nobundle", ...)]`.
(removed, static_nobundle, "1.16.0", Some(37403),
Some(r#"subsumed by `#[link(kind = "static", modifiers = "-bundle", ...)]`"#)),

View file

@ -300,8 +300,6 @@ declare_features! (
(internal, rustdoc_internals, "1.58.0", Some(90418)),
/// Allows using the `rustdoc::missing_doc_code_examples` lint
(unstable, rustdoc_missing_doc_code_examples, "1.31.0", Some(101730)),
/// Allows using `#[start]` on a function indicating that it is the program entrypoint.
(unstable, start, "1.0.0", Some(29633)),
/// Allows using `#[structural_match]` which indicates that a type is structurally matchable.
/// FIXME: Subsumed by trait `StructuralPartialEq`, cannot move to removed until a library
/// feature with the same name exists.

View file

@ -332,6 +332,10 @@ language_item_table! {
FallbackSurfaceDrop, sym::fallback_surface_drop, fallback_surface_drop_fn, Target::Fn, GenericRequirement::None;
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;
/// For all binary crates without `#![no_main]`, Rust will generate a "main" function.
/// The exact name and signature are target-dependent. The "main" function will invoke
/// this lang item, passing it the `argc` and `argv` (or null, if those don't exist
/// on the current target) as well as the user-defined `fn main` from the binary crate.
Start, sym::start, start_fn, Target::Fn, GenericRequirement::Exact(1);
EhPersonality, sym::eh_personality, eh_personality, Target::Fn, GenericRequirement::None;

View file

@ -489,21 +489,6 @@ hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is hi
hir_analysis_specialization_trait = implementing `rustc_specialization_trait` traits is unstable
.help = add `#![feature(min_specialization)]` to the crate attributes to enable
hir_analysis_start_function_parameters = `#[start]` function is not allowed to have type parameters
.label = `#[start]` function cannot have type parameters
hir_analysis_start_function_where = `#[start]` function is not allowed to have a `where` clause
.label = `#[start]` function cannot have a `where` clause
hir_analysis_start_not_async = `#[start]` function is not allowed to be `async`
.label = `#[start]` is not allowed to be `async`
hir_analysis_start_not_target_feature = `#[start]` function is not allowed to have `#[target_feature]`
.label = `#[start]` function is not allowed to have `#[target_feature]`
hir_analysis_start_not_track_caller = `#[start]` function is not allowed to be `#[track_caller]`
.label = `#[start]` function is not allowed to be `#[track_caller]`
hir_analysis_static_specialize = cannot specialize on `'static` lifetime
hir_analysis_tait_forward_compat = item constrains opaque type that is not in its signature

View file

@ -5,7 +5,7 @@ use rustc_hir as hir;
use rustc_hir::Node;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::span_bug;
use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode};
use rustc_middle::ty::{self, TyCtxt, TypingMode};
use rustc_session::config::EntryFnType;
use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
use rustc_span::{Span, sym};
@ -18,7 +18,6 @@ use crate::errors;
pub(crate) fn check_for_entry_fn(tcx: TyCtxt<'_>) {
match tcx.entry_fn(()) {
Some((def_id, EntryFnType::Main { .. })) => check_main_fn_ty(tcx, def_id),
Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
_ => {}
}
}
@ -192,83 +191,3 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
});
}
}
fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
let start_def_id = start_def_id.expect_local();
let start_id = tcx.local_def_id_to_hir_id(start_def_id);
let start_span = tcx.def_span(start_def_id);
let start_t = tcx.type_of(start_def_id).instantiate_identity();
match start_t.kind() {
ty::FnDef(..) => {
if let Node::Item(it) = tcx.hir_node(start_id) {
if let hir::ItemKind::Fn { sig, generics, .. } = &it.kind {
let mut error = false;
if !generics.params.is_empty() {
tcx.dcx().emit_err(errors::StartFunctionParameters { span: generics.span });
error = true;
}
if generics.has_where_clause_predicates {
tcx.dcx().emit_err(errors::StartFunctionWhere {
span: generics.where_clause_span,
});
error = true;
}
if sig.header.asyncness.is_async() {
let span = tcx.def_span(it.owner_id);
tcx.dcx().emit_err(errors::StartAsync { span });
error = true;
}
let attrs = tcx.hir().attrs(start_id);
for attr in attrs {
if attr.has_name(sym::track_caller) {
tcx.dcx().emit_err(errors::StartTrackCaller {
span: attr.span,
start: start_span,
});
error = true;
}
if attr.has_name(sym::target_feature)
// Calling functions with `#[target_feature]` is
// not unsafe on WASM, see #84988
&& !tcx.sess.target.is_like_wasm
&& !tcx.sess.opts.actually_rustdoc
{
tcx.dcx().emit_err(errors::StartTargetFeature {
span: attr.span,
start: start_span,
});
error = true;
}
}
if error {
return;
}
}
}
let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig(
[tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))],
tcx.types.isize,
false,
hir::Safety::Safe,
ExternAbi::Rust,
));
let _ = check_function_signature(
tcx,
ObligationCause::new(
start_span,
start_def_id,
ObligationCauseCode::StartFunctionType,
),
start_def_id.into(),
expected_sig,
);
}
_ => {
span_bug!(start_span, "start has a non-function type: found `{}`", start_t);
}
}
}

View file

@ -619,48 +619,6 @@ pub(crate) struct TargetFeatureOnMain {
pub main: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_start_not_track_caller)]
pub(crate) struct StartTrackCaller {
#[primary_span]
pub span: Span,
#[label]
pub start: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_start_not_target_feature)]
pub(crate) struct StartTargetFeature {
#[primary_span]
pub span: Span,
#[label]
pub start: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_start_not_async, code = E0752)]
pub(crate) struct StartAsync {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_start_function_where, code = E0647)]
pub(crate) struct StartFunctionWhere {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_start_function_parameters, code = E0132)]
pub(crate) struct StartFunctionParameters {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_main_function_return_type_generic, code = E0131)]
pub(crate) struct MainFunctionReturnTypeGeneric {

View file

@ -345,9 +345,6 @@ pub enum ObligationCauseCode<'tcx> {
/// `main` has wrong type
MainFunctionType,
/// `start` has wrong type
StartFunctionType,
/// language function has wrong type
LangFunctionType(Symbol),

View file

@ -502,11 +502,6 @@ passes_multiple_rustc_main =
.first = first `#[rustc_main]` function
.additional = additional `#[rustc_main]` function
passes_multiple_start_functions =
multiple `start` functions
.label = multiple `start` functions
.previous = previous `#[start]` function here
passes_must_not_suspend =
`must_not_suspend` attribute should be applied to a struct, enum, union, or trait
.label = is not a struct, enum, union, or trait

View file

@ -275,7 +275,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| sym::lang
| sym::needs_allocator
| sym::default_lib_allocator
| sym::start
| sym::custom_mir,
..
] => {}
@ -2655,7 +2654,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
sym::repr,
sym::path,
sym::automatically_derived,
sym::start,
sym::rustc_main,
sym::derive,
sym::test,

View file

@ -10,9 +10,7 @@ use rustc_session::RemapFileNameExt;
use rustc_session::config::{CrateType, EntryFnType, RemapPathScopeComponents, sigpipe};
use rustc_span::{Span, Symbol, sym};
use crate::errors::{
AttrOnlyInFunctions, ExternMain, MultipleRustcMain, MultipleStartFunctions, NoMainErr,
};
use crate::errors::{AttrOnlyInFunctions, ExternMain, MultipleRustcMain, NoMainErr};
struct EntryContext<'tcx> {
tcx: TyCtxt<'tcx>,
@ -20,9 +18,6 @@ struct EntryContext<'tcx> {
/// The function has the `#[rustc_main]` attribute.
rustc_main_fn: Option<(LocalDefId, Span)>,
/// The function that has the attribute `#[start]` on it.
start_fn: Option<(LocalDefId, Span)>,
/// 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<Span>,
@ -40,8 +35,7 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
return None;
}
let mut ctxt =
EntryContext { tcx, rustc_main_fn: None, start_fn: None, non_main_fns: Vec::new() };
let mut ctxt = EntryContext { tcx, rustc_main_fn: None, non_main_fns: Vec::new() };
for id in tcx.hir().items() {
check_and_search_item(id, &mut ctxt);
@ -57,7 +51,7 @@ fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Opti
fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) {
for attr in [sym::start, sym::rustc_main] {
for attr in [sym::rustc_main] {
if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr });
}
@ -91,24 +85,11 @@ fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
});
}
}
EntryPointType::Start => {
if ctxt.start_fn.is_none() {
ctxt.start_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
} else {
ctxt.tcx.dcx().emit_err(MultipleStartFunctions {
span: ctxt.tcx.def_span(id.owner_id),
labeled: ctxt.tcx.def_span(id.owner_id.to_def_id()),
previous: ctxt.start_fn.unwrap().1,
});
}
}
}
}
fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> {
if let Some((def_id, _)) = visitor.start_fn {
Some((def_id.to_def_id(), EntryFnType::Start))
} else if let Some((local_def_id, _)) = visitor.rustc_main_fn {
if let Some((local_def_id, _)) = visitor.rustc_main_fn {
let def_id = local_def_id.to_def_id();
Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) }))
} else {

View file

@ -1313,17 +1313,6 @@ pub(crate) struct MultipleRustcMain {
pub additional: Span,
}
#[derive(Diagnostic)]
#[diag(passes_multiple_start_functions, code = E0138)]
pub(crate) struct MultipleStartFunctions {
#[primary_span]
pub span: Span,
#[label]
pub labeled: Span,
#[label(passes_previous)]
pub previous: Span,
}
#[derive(Diagnostic)]
#[diag(passes_extern_main)]
pub(crate) struct ExternMain {

View file

@ -1275,7 +1275,6 @@ pub enum EntryFnType {
/// and an `include!()`.
sigpipe: u8,
},
Start,
}
#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]

View file

@ -261,7 +261,6 @@ trait_selection_oc_fn_lang_correct_type = {$lang_item_name ->
*[lang_item_name] lang item `{$lang_item_name}`
} function has wrong type
trait_selection_oc_fn_main_correct_type = `main` function has wrong type
trait_selection_oc_fn_start_correct_type = `#[start]` function has wrong type
trait_selection_oc_generic = mismatched types
trait_selection_oc_if_else_different = `if` and `else` have incompatible types
@ -396,7 +395,6 @@ trait_selection_subtype = ...so that the {$requirement ->
[if_else_different] `if` and `else` have incompatible types
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
[fn_start_correct_type] `#[start]` function has the correct type
[fn_lang_correct_type] lang item function has the correct type
[intrinsic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
@ -410,7 +408,6 @@ trait_selection_subtype_2 = ...so that {$requirement ->
[if_else_different] `if` and `else` have incompatible types
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
[fn_start_correct_type] `#[start]` function has the correct type
[fn_lang_correct_type] lang item function has the correct type
[intrinsic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type

View file

@ -2310,7 +2310,6 @@ impl<'tcx> ObligationCause<'tcx> {
| ObligationCauseCode::MatchExpressionArm(_)
| ObligationCauseCode::IfExpression { .. }
| ObligationCauseCode::LetElse
| ObligationCauseCode::StartFunctionType
| ObligationCauseCode::LangFunctionType(_)
| ObligationCauseCode::IntrinsicType
| ObligationCauseCode::MethodReceiver => FailureCode::Error0308,
@ -2368,9 +2367,6 @@ impl<'tcx> ObligationCause<'tcx> {
ObligationCauseCode::MainFunctionType => {
ObligationCauseFailureCode::FnMainCorrectType { span }
}
ObligationCauseCode::StartFunctionType => {
ObligationCauseFailureCode::FnStartCorrectType { span, subdiags }
}
&ObligationCauseCode::LangFunctionType(lang_item_name) => {
ObligationCauseFailureCode::FnLangCorrectType { span, subdiags, lang_item_name }
}
@ -2413,7 +2409,6 @@ impl<'tcx> ObligationCause<'tcx> {
"const is compatible with trait"
}
ObligationCauseCode::MainFunctionType => "`main` function has the correct type",
ObligationCauseCode::StartFunctionType => "`#[start]` function has the correct type",
ObligationCauseCode::LangFunctionType(_) => "lang item function has the correct type",
ObligationCauseCode::IntrinsicType => "intrinsic has the correct type",
ObligationCauseCode::MethodReceiver => "method receiver has the correct type",
@ -2434,7 +2429,6 @@ impl IntoDiagArg for ObligationCauseAsDiagArg<'_> {
"const_compat"
}
ObligationCauseCode::MainFunctionType => "fn_main_correct_type",
ObligationCauseCode::StartFunctionType => "fn_start_correct_type",
ObligationCauseCode::LangFunctionType(_) => "fn_lang_correct_type",
ObligationCauseCode::IntrinsicType => "intrinsic_correct_type",
ObligationCauseCode::MethodReceiver => "method_correct_type",

View file

@ -2740,7 +2740,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
| ObligationCauseCode::IfExpression { .. }
| ObligationCauseCode::IfExpressionWithNoElse
| ObligationCauseCode::MainFunctionType
| ObligationCauseCode::StartFunctionType
| ObligationCauseCode::LangFunctionType(_)
| ObligationCauseCode::IntrinsicType
| ObligationCauseCode::MethodReceiver

View file

@ -1695,13 +1695,6 @@ pub enum ObligationCauseFailureCode {
#[primary_span]
span: Span,
},
#[diag(trait_selection_oc_fn_start_correct_type, code = E0308)]
FnStartCorrectType {
#[primary_span]
span: Span,
#[subdiagnostic]
subdiags: Vec<TypeErrorAdditionalDiags>,
},
#[diag(trait_selection_oc_fn_lang_correct_type, code = E0308)]
FnLangCorrectType {
#[primary_span]