Adds termination_trait feature gate
This commit is contained in:
parent
8f539b09df
commit
c7a57d2855
7 changed files with 46 additions and 27 deletions
|
@ -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,28 +1065,29 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
|
|||
}
|
||||
fcx.demand_suptype(span, ret_ty, actual_return_ty);
|
||||
|
||||
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 fcx.tcx.lang_items().termination().is_some() {
|
||||
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 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()));
|
||||
traits::Obligation::new(
|
||||
cause, param_env, trait_ref.to_predicate()));
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(fcx, gen_ty)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<T: Termination, E: Error> Termination for Result<T, E> {
|
||||
fn report(self) -> i32 {
|
||||
match self {
|
||||
|
@ -47,7 +47,7 @@ impl<T: Termination, E: Error> Termination for Result<T, E> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "termination_trait", issue = "0")]
|
||||
#[unstable(feature = "termination_trait", issue = "43301")]
|
||||
fn print_error<E: Error>(err: E) {
|
||||
eprintln!("Error: {}", err.description());
|
||||
|
||||
|
@ -56,19 +56,19 @@ fn print_error<E: 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
|
||||
|
|
|
@ -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! (
|
||||
|
|
13
src/test/compile-fail/feature-gate-termination_trait.rs
Normal file
13
src/test/compile-fail/feature-gate-termination_trait.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue