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); + 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); - 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())); - }, - _ => {}, + 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