From d7918fb2e889c5ccb58ab8b97d2581cc763f2306 Mon Sep 17 00:00:00 2001 From: Bastian Köcher Date: Sun, 3 Dec 2017 22:16:24 +0100 Subject: Implements RFC 1937: `?` in `main` This is the first part of the RFC 1937 that supports new `Termination` trait in the rust `main` function. --- src/libstd/lib.rs | 6 ++++ src/libstd/rt.rs | 45 +++++++++++++++++++++++++++- src/libstd/termination.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 src/libstd/termination.rs (limited to 'src/libstd') diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 12e6231136e..3a7a57fe2b8 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -308,6 +308,7 @@ #![feature(str_char)] #![feature(str_internals)] #![feature(str_utf16)] +#![feature(termination_trait)] #![feature(test, rustc_private)] #![feature(thread_local)] #![feature(toowned_clone_into)] @@ -499,6 +500,11 @@ mod memchr; // The runtime entry point and a few unstable public functions used by the // compiler pub mod rt; +// The trait to support returning arbitrary types in the main function +mod termination; + +#[unstable(feature = "termination_trait", issue = "0")] +pub use self::termination::Termination; // Include a number of private modules that exist solely to provide // the rustdoc documentation for primitive types. Using `include!` diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 40b24cedcdc..2b75201ad2b 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -26,7 +26,50 @@ // Reexport some of our utilities which are expected by other crates. pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count}; -#[cfg(not(test))] +#[cfg(not(any(test, stage0)))] +#[lang = "start"] +fn lang_start + (main: fn() -> T, argc: isize, argv: *const *const u8) -> ! +{ + use panic; + use sys; + use sys_common; + use sys_common::thread_info; + use thread::Thread; + use process; + #[cfg(not(feature = "backtrace"))] + use mem; + + sys::init(); + + process::exit(unsafe { + let main_guard = sys::thread::guard::init(); + sys::stack_overflow::init(); + + // Next, set up the current Thread with the guard information we just + // created. Note that this isn't necessary in general for new threads, + // but we just do this to name the main thread and to give it correct + // info about the stack bounds. + let thread = Thread::new(Some("main".to_owned())); + thread_info::set(main_guard, thread); + + // Store our args if necessary in a squirreled away location + sys::args::init(argc, argv); + + // Let's run some code! + #[cfg(feature = "backtrace")] + let exit_code = panic::catch_unwind(|| { + ::sys_common::backtrace::__rust_begin_short_backtrace(move || main().report()) + }); + #[cfg(not(feature = "backtrace"))] + let exit_code = panic::catch_unwind(mem::transmute::<_, fn()>(main).report()); + + sys_common::cleanup(); + exit_code.unwrap_or(101) + }); +} + +#[cfg(all(not(test), stage0))] #[lang = "start"] fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize { use panic; diff --git a/src/libstd/termination.rs b/src/libstd/termination.rs new file mode 100644 index 00000000000..a08d3dd2d52 --- /dev/null +++ b/src/libstd/termination.rs @@ -0,0 +1,74 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use error::Error; +use libc; + +/// A trait for implementing arbitrary return types in the `main` function. +/// +/// The c-main function only supports to return integers as return type. +/// So, every type implementing the `Termination` trait has to be converted +/// to an integer. +/// +/// The default implementations are returning `libc::EXIT_SUCCESS` to indicate +/// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned. +#[cfg_attr(not(stage0), lang = "termination")] +#[unstable(feature = "termination_trait", issue = "0")] +pub trait Termination { + /// Is called to get the representation of the value as status code. + /// This status code is returned to the operating system. + fn report(self) -> i32; +} + +#[unstable(feature = "termination_trait", issue = "0")] +impl Termination for () { + fn report(self) -> i32 { libc::EXIT_SUCCESS } +} + +#[unstable(feature = "termination_trait", issue = "0")] +impl Termination for Result { + fn report(self) -> i32 { + match self { + Ok(val) => val.report(), + Err(err) => { + print_error(err); + libc::EXIT_FAILURE + } + } + } +} + +#[unstable(feature = "termination_trait", issue = "0")] +fn print_error(err: E) { + eprintln!("Error: {}", err.description()); + + if let Some(ref err) = err.cause() { + eprintln!("Caused by: {}", err.description()); + } +} + +#[unstable(feature = "termination_trait", issue = "0")] +impl Termination for ! { + fn report(self) -> i32 { unreachable!(); } +} + +#[unstable(feature = "termination_trait", issue = "0")] +impl Termination for bool { + fn report(self) -> i32 { + if self { libc::EXIT_SUCCESS } else { libc::EXIT_FAILURE } + } +} + +#[unstable(feature = "termination_trait", issue = "0")] +impl Termination for i32 { + fn report(self) -> i32 { + self + } +} -- cgit 1.4.1-3-g733a5 From 99a108c03654cd9d2df21223eb55a5dfd6552cb8 Mon Sep 17 00:00:00 2001 From: Bastian Köcher Date: Thu, 21 Dec 2017 12:03:01 +0100 Subject: Fixes compilation errors and adds proposed improvements --- src/librustc_mir/monomorphize/collector.rs | 5 ++--- src/librustc_mir/monomorphize/partitioning.rs | 7 ++----- src/libstd/termination.rs | 2 ++ 3 files changed, 6 insertions(+), 8 deletions(-) (limited to 'src/libstd') diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index afd895eb7ca..ccb648cd929 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -195,7 +195,6 @@ use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; use rustc::middle::const_val::ConstVal; use rustc::middle::lang_items::{ExchangeMallocFnLangItem,StartFnLangItem}; -use rustc::middle::trans::TransItem; use rustc::traits; use rustc::ty::subst::{Substs, Kind}; use rustc::ty::{self, TypeFoldable, Ty, TyCtxt}; @@ -1001,7 +1000,7 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> { debug!("RootCollector::push_if_root: found root def_id={:?}", def_id); let instance = Instance::mono(self.tcx, def_id); - self.output.push(create_fn_trans_item(instance)); + self.output.push(create_fn_mono_item(instance)); self.push_extra_entry_roots(def_id); } @@ -1041,7 +1040,7 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> { self.tcx.mk_substs(iter::once(Kind::from(main_ret_ty))) ).unwrap(); - self.output.push(create_fn_trans_item(start_instance)); + self.output.push(create_fn_mono_item(start_instance)); } } diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index e34698da4da..1a4849ac199 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -106,8 +106,7 @@ use monomorphize::collector::InliningMap; use rustc::dep_graph::WorkProductId; use rustc::hir::def_id::DefId; use rustc::hir::map::DefPathData; -use rustc::middle::lang_items::StartFnLangItem; -use rustc::middle::trans::{Linkage, Visibility}; +use rustc::mir::mono::{Linkage, Visibility}; use rustc::ty::{self, TyCtxt, InstanceDef}; use rustc::ty::item_path::characteristic_def_id_of_type; use rustc::util::nodemap::{FxHashMap, FxHashSet}; @@ -313,11 +312,9 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, MonoItem::Fn(ref instance) => { let visibility = match instance.def { InstanceDef::Item(def_id) => { - let start_def_id = tcx.lang_items().require(StartFnLangItem); - // If we encounter the lang start item, we set the visibility to // default. - if start_def_id == Ok(def_id) { + if tcx.lang_items().start_fn() == Some(def_id) { Visibility::Default } else if def_id.is_local() { if tcx.is_exported_symbol(def_id) { diff --git a/src/libstd/termination.rs b/src/libstd/termination.rs index a08d3dd2d52..5eeaa542b41 100644 --- a/src/libstd/termination.rs +++ b/src/libstd/termination.rs @@ -21,6 +21,8 @@ use libc; /// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned. #[cfg_attr(not(stage0), lang = "termination")] #[unstable(feature = "termination_trait", issue = "0")] +#[rustc_on_unimplemented = + "`main` can only return types that implement {Termination}, not `{Self}`"] pub trait Termination { /// Is called to get the representation of the value as status code. /// This status code is returned to the operating system. -- cgit 1.4.1-3-g733a5 From c7a57d285517f1e22d34ace98fbb0c64e40b12bc Mon Sep 17 00:00:00 2001 From: Bastian Köcher Date: Fri, 22 Dec 2017 01:11:57 +0100 Subject: Adds termination_trait feature gate --- src/librustc_typeck/check/mod.rs | 38 +++++++++++----------- src/librustc_typeck/lib.rs | 3 +- src/libstd/lib.rs | 2 +- src/libstd/termination.rs | 14 ++++---- src/libsyntax/feature_gate.rs | 3 ++ .../compile-fail/feature-gate-termination_trait.rs | 13 ++++++++ .../termination-trait-not-satisfied.rs | 2 ++ 7 files changed, 47 insertions(+), 28 deletions(-) create mode 100644 src/test/compile-fail/feature-gate-termination_trait.rs (limited to 'src/libstd') diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e99633519f4..7a49c3549ab 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -93,7 +93,6 @@ use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin}; use rustc::infer::anon_types::AnonTypeDecl; use rustc::infer::type_variable::{TypeVariableOrigin}; use rustc::middle::region; -use rustc::middle::lang_items::TerminationTraitLangItem; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode}; use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue}; @@ -1066,24 +1065,25 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, } fcx.demand_suptype(span, ret_ty, actual_return_ty); - // If the termination trait language item is activated, check that the main return type - // implements the termination trait. - if fcx.tcx.lang_items().termination().is_some() { - if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() { - if id == fn_id { - match fcx.sess().entry_type.get() { - Some(config::EntryMain) => { - let term_id = fcx.tcx.require_lang_item(TerminationTraitLangItem); - - let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty))); - let trait_ref = ty::TraitRef::new(term_id, substs); - let cause = traits::ObligationCause::new( - span, fn_id, ObligationCauseCode::MainFunctionType); - - inherited.register_predicate( - traits::Obligation::new(cause, param_env, trait_ref.to_predicate())); - }, - _ => {}, + if fcx.tcx.sess.features.borrow().termination_trait { + // If the termination trait language item is activated, check that the main return type + // implements the termination trait. + if let Some(term_id) = fcx.tcx.lang_items().termination() { + if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() { + if id == fn_id { + match fcx.sess().entry_type.get() { + Some(config::EntryMain) => { + let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty))); + let trait_ref = ty::TraitRef::new(term_id, substs); + let cause = traits::ObligationCause::new( + span, fn_id, ObligationCauseCode::MainFunctionType); + + inherited.register_predicate( + traits::Obligation::new( + cause, param_env, trait_ref.to_predicate())); + }, + _ => {}, + } } } } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index f02998f7edf..0b2f59abf4f 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -203,7 +203,8 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } let actual = tcx.fn_sig(main_def_id); - let expected_return_type = if tcx.lang_items().termination().is_some() { + let expected_return_type = if tcx.lang_items().termination().is_some() + && tcx.sess.features.borrow().termination_trait { // we take the return type of the given main function, the real check is done // in `check_fn` actual.output().skip_binder() diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 3a7a57fe2b8..171c108e3aa 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -503,7 +503,7 @@ pub mod rt; // The trait to support returning arbitrary types in the main function mod termination; -#[unstable(feature = "termination_trait", issue = "0")] +#[unstable(feature = "termination_trait", issue = "43301")] pub use self::termination::Termination; // Include a number of private modules that exist solely to provide diff --git a/src/libstd/termination.rs b/src/libstd/termination.rs index 5eeaa542b41..ee1dc5470a8 100644 --- a/src/libstd/termination.rs +++ b/src/libstd/termination.rs @@ -20,7 +20,7 @@ use libc; /// The default implementations are returning `libc::EXIT_SUCCESS` to indicate /// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned. #[cfg_attr(not(stage0), lang = "termination")] -#[unstable(feature = "termination_trait", issue = "0")] +#[unstable(feature = "termination_trait", issue = "43301")] #[rustc_on_unimplemented = "`main` can only return types that implement {Termination}, not `{Self}`"] pub trait Termination { @@ -29,12 +29,12 @@ pub trait Termination { fn report(self) -> i32; } -#[unstable(feature = "termination_trait", issue = "0")] +#[unstable(feature = "termination_trait", issue = "43301")] impl Termination for () { fn report(self) -> i32 { libc::EXIT_SUCCESS } } -#[unstable(feature = "termination_trait", issue = "0")] +#[unstable(feature = "termination_trait", issue = "43301")] impl Termination for Result { fn report(self) -> i32 { match self { @@ -47,7 +47,7 @@ impl Termination for Result { } } -#[unstable(feature = "termination_trait", issue = "0")] +#[unstable(feature = "termination_trait", issue = "43301")] fn print_error(err: E) { eprintln!("Error: {}", err.description()); @@ -56,19 +56,19 @@ fn print_error(err: E) { } } -#[unstable(feature = "termination_trait", issue = "0")] +#[unstable(feature = "termination_trait", issue = "43301")] impl Termination for ! { fn report(self) -> i32 { unreachable!(); } } -#[unstable(feature = "termination_trait", issue = "0")] +#[unstable(feature = "termination_trait", issue = "43301")] impl Termination for bool { fn report(self) -> i32 { if self { libc::EXIT_SUCCESS } else { libc::EXIT_FAILURE } } } -#[unstable(feature = "termination_trait", issue = "0")] +#[unstable(feature = "termination_trait", issue = "43301")] impl Termination for i32 { fn report(self) -> i32 { self diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index f8d6b419f7a..dde917b4d95 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -444,6 +444,9 @@ declare_features! ( // Nested `impl Trait` (active, nested_impl_trait, "1.24.0", Some(34511)), + + // Termination trait in main (RFC 1937) + (active, termination_trait, "1.24.0", Some(43301)), ); declare_features! ( diff --git a/src/test/compile-fail/feature-gate-termination_trait.rs b/src/test/compile-fail/feature-gate-termination_trait.rs new file mode 100644 index 00000000000..5a56445b64e --- /dev/null +++ b/src/test/compile-fail/feature-gate-termination_trait.rs @@ -0,0 +1,13 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() -> i32 { //~ ERROR main function has wrong type [E0580] + 0 +} diff --git a/src/test/compile-fail/termination-trait-not-satisfied.rs b/src/test/compile-fail/termination-trait-not-satisfied.rs index 178a9b8cf59..788c38c55be 100644 --- a/src/test/compile-fail/termination-trait-not-satisfied.rs +++ b/src/test/compile-fail/termination-trait-not-satisfied.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(termination_trait)] + struct ReturnType {} fn main() -> ReturnType { //~ ERROR `ReturnType: std::Termination` is not satisfied -- cgit 1.4.1-3-g733a5 From 88bf2b4630ca52c4949665ff3016731fd924eaf1 Mon Sep 17 00:00:00 2001 From: Bastian Köcher Date: Fri, 22 Dec 2017 16:11:09 +0100 Subject: Removes some obscure transmute call in `lang_start` --- src/libstd/rt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 2b75201ad2b..bfea64153c6 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -62,7 +62,7 @@ fn lang_start ::sys_common::backtrace::__rust_begin_short_backtrace(move || main().report()) }); #[cfg(not(feature = "backtrace"))] - let exit_code = panic::catch_unwind(mem::transmute::<_, fn()>(main).report()); + let exit_code = panic::catch_unwind(|| main().report()); sys_common::cleanup(); exit_code.unwrap_or(101) -- cgit 1.4.1-3-g733a5 From faff382c3d5756265726e57d0928b5a1815f5485 Mon Sep 17 00:00:00 2001 From: Bastian Köcher Date: Fri, 22 Dec 2017 18:23:47 +0100 Subject: Don't emit the termination lang item in tests --- src/libstd/termination.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/termination.rs b/src/libstd/termination.rs index ee1dc5470a8..cfbeff0de15 100644 --- a/src/libstd/termination.rs +++ b/src/libstd/termination.rs @@ -19,7 +19,7 @@ use libc; /// /// The default implementations are returning `libc::EXIT_SUCCESS` to indicate /// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned. -#[cfg_attr(not(stage0), lang = "termination")] +#[cfg_attr(not(any(stage0, test)), lang = "termination")] #[unstable(feature = "termination_trait", issue = "43301")] #[rustc_on_unimplemented = "`main` can only return types that implement {Termination}, not `{Self}`"] -- cgit 1.4.1-3-g733a5 From 072f3ebd878ad044abedd3324469ae1b01eca67b Mon Sep 17 00:00:00 2001 From: Bastian Köcher Date: Fri, 22 Dec 2017 20:39:31 +0100 Subject: Use move for optimization purposes --- src/libstd/rt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index bfea64153c6..1fd7c270d19 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -62,7 +62,7 @@ fn lang_start ::sys_common::backtrace::__rust_begin_short_backtrace(move || main().report()) }); #[cfg(not(feature = "backtrace"))] - let exit_code = panic::catch_unwind(|| main().report()); + let exit_code = panic::catch_unwind(move || main().report()); sys_common::cleanup(); exit_code.unwrap_or(101) -- cgit 1.4.1-3-g733a5 From dbbba553828b1763951fc0eb02fa436ac61d9a95 Mon Sep 17 00:00:00 2001 From: Bastian Köcher Date: Sat, 23 Dec 2017 00:47:25 +0100 Subject: Rework the exit failure and success declaration for wasm32 --- src/libstd/termination.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/termination.rs b/src/libstd/termination.rs index cfbeff0de15..61137ba4922 100644 --- a/src/libstd/termination.rs +++ b/src/libstd/termination.rs @@ -9,7 +9,17 @@ // except according to those terms. use error::Error; -use libc; +#[cfg(target_arch = "wasm32")] +mod exit { + pub const SUCCESS: i32 = 0; + pub const FAILURE: i32 = 1; +} +#[cfg(not(target_arch = "wasm32"))] +mod exit { + use libc; + pub const SUCCESS: i32 = libc::EXIT_SUCCESS; + pub const FAILURE: i32 = libc::EXIT_FAILURE; +} /// A trait for implementing arbitrary return types in the `main` function. /// @@ -31,7 +41,7 @@ pub trait Termination { #[unstable(feature = "termination_trait", issue = "43301")] impl Termination for () { - fn report(self) -> i32 { libc::EXIT_SUCCESS } + fn report(self) -> i32 { exit::SUCCESS } } #[unstable(feature = "termination_trait", issue = "43301")] @@ -41,7 +51,7 @@ impl Termination for Result { Ok(val) => val.report(), Err(err) => { print_error(err); - libc::EXIT_FAILURE + exit::FAILURE } } } @@ -64,7 +74,7 @@ impl Termination for ! { #[unstable(feature = "termination_trait", issue = "43301")] impl Termination for bool { fn report(self) -> i32 { - if self { libc::EXIT_SUCCESS } else { libc::EXIT_FAILURE } + if self { exit::SUCCESS } else { exit::FAILURE } } } -- cgit 1.4.1-3-g733a5 From 7dfec34a20af59e50f59f73799f471795a50eeb8 Mon Sep 17 00:00:00 2001 From: Bastian Köcher Date: Sun, 24 Dec 2017 00:15:38 +0100 Subject: Split `lang_start` in two functions to reduce generated code --- src/libstd/rt.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 1fd7c270d19..27c20be7a9a 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -26,10 +26,11 @@ // Reexport some of our utilities which are expected by other crates. pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count}; +// To reduce the generated code of the new `lang_start`, this function is doing +// the real work. #[cfg(not(any(test, stage0)))] -#[lang = "start"] -fn lang_start - (main: fn() -> T, argc: isize, argv: *const *const u8) -> ! +fn lang_start_real(main: F, argc: isize, argv: *const *const u8) -> ! + where F: FnOnce() -> i32 + Send + ::panic::UnwindSafe + 'static { use panic; use sys; @@ -59,16 +60,24 @@ fn lang_start // Let's run some code! #[cfg(feature = "backtrace")] let exit_code = panic::catch_unwind(|| { - ::sys_common::backtrace::__rust_begin_short_backtrace(move || main().report()) + ::sys_common::backtrace::__rust_begin_short_backtrace(move || main()) }); #[cfg(not(feature = "backtrace"))] - let exit_code = panic::catch_unwind(move || main().report()); + let exit_code = panic::catch_unwind(move || main()); sys_common::cleanup(); exit_code.unwrap_or(101) }); } +#[cfg(not(any(test, stage0)))] +#[lang = "start"] +fn lang_start + (main: fn() -> T, argc: isize, argv: *const *const u8) -> ! +{ + lang_start_real(move || main().report(), argc, argv) +} + #[cfg(all(not(test), stage0))] #[lang = "start"] fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize { -- cgit 1.4.1-3-g733a5 From 81e375dba5e7915548dc6067cf16c62cdbce4853 Mon Sep 17 00:00:00 2001 From: Bastian Köcher Date: Sun, 24 Dec 2017 00:35:38 +0100 Subject: Change name of `lang_start_real` to `lang_start_internal` Also remove `'static` from `__rust_begin_short_backtrace` --- src/libstd/rt.rs | 7 +++---- src/libstd/sys_common/backtrace.rs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 27c20be7a9a..d17dfb25f31 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -29,9 +29,8 @@ pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count}; // To reduce the generated code of the new `lang_start`, this function is doing // the real work. #[cfg(not(any(test, stage0)))] -fn lang_start_real(main: F, argc: isize, argv: *const *const u8) -> ! - where F: FnOnce() -> i32 + Send + ::panic::UnwindSafe + 'static -{ +fn lang_start_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe), + argc: isize, argv: *const *const u8) -> ! { use panic; use sys; use sys_common; @@ -75,7 +74,7 @@ fn lang_start_real(main: F, argc: isize, argv: *const *const u8) -> ! fn lang_start (main: fn() -> T, argc: isize, argv: *const *const u8) -> ! { - lang_start_real(move || main().report(), argc, argv) + lang_start_internal(&move || main().report(), argc, argv) } #[cfg(all(not(test), stage0))] diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index b5cf6d7d34f..36cbce2df75 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -128,7 +128,7 @@ fn filter_frames(frames: &[Frame], /// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. #[inline(never)] pub fn __rust_begin_short_backtrace(f: F) -> T - where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static + where F: FnOnce() -> T, F: Send, T: Send { f() } -- cgit 1.4.1-3-g733a5 From 5a4298b6d36c493cabeae1453119d1edc96e1472 Mon Sep 17 00:00:00 2001 From: Bastian Köcher Date: Tue, 26 Dec 2017 23:52:20 +0100 Subject: Don't use `process::exit` as it is an `unreachable` on wasm32 --- src/librustc_trans/base.rs | 12 ++---------- src/libstd/rt.rs | 11 +++++------ 2 files changed, 7 insertions(+), 16 deletions(-) (limited to 'src/libstd') diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 3955171f939..680821d6d68 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -552,10 +552,7 @@ fn maybe_create_entry_wrapper(ccx: &CrateContext) { rust_main: ValueRef, rust_main_def_id: DefId, use_start_lang_item: bool) { - // The libstd lang_start function does not return anything, while user defined lang start - // returns a isize - let start_output_ty = if use_start_lang_item { Type::void(ccx) } else { Type::c_int(ccx) }; - let llfty = Type::func(&[Type::c_int(ccx), Type::i8p(ccx).ptr_to()], &start_output_ty); + let llfty = Type::func(&[Type::c_int(ccx), Type::i8p(ccx).ptr_to()], &Type::c_int(ccx)); let main_ret_ty = ccx.tcx().fn_sig(rust_main_def_id).output(); // Given that `main()` has no arguments, @@ -600,12 +597,7 @@ fn maybe_create_entry_wrapper(ccx: &CrateContext) { }; let result = bld.call(start_fn, &args, None); - - if use_start_lang_item { - bld.ret_void(); - } else { - bld.ret(bld.intcast(result, Type::c_int(ccx), true)); - } + bld.ret(bld.intcast(result, Type::c_int(ccx), true)); } } diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index d17dfb25f31..e2c1bba50c4 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -30,19 +30,18 @@ pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count}; // the real work. #[cfg(not(any(test, stage0)))] fn lang_start_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe), - argc: isize, argv: *const *const u8) -> ! { + argc: isize, argv: *const *const u8) -> isize { use panic; use sys; use sys_common; use sys_common::thread_info; use thread::Thread; - use process; #[cfg(not(feature = "backtrace"))] use mem; sys::init(); - process::exit(unsafe { + unsafe { let main_guard = sys::thread::guard::init(); sys::stack_overflow::init(); @@ -65,14 +64,14 @@ fn lang_start_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe), let exit_code = panic::catch_unwind(move || main()); sys_common::cleanup(); - exit_code.unwrap_or(101) - }); + exit_code.unwrap_or(101) as isize + } } #[cfg(not(any(test, stage0)))] #[lang = "start"] fn lang_start - (main: fn() -> T, argc: isize, argv: *const *const u8) -> ! + (main: fn() -> T, argc: isize, argv: *const *const u8) -> isize { lang_start_internal(&move || main().report(), argc, argv) } -- cgit 1.4.1-3-g733a5