Fall back to main -> () when termination trait language item is not enabled

This commit is contained in:
Bastian Köcher 2017-12-21 14:20:03 +01:00
parent f842f7547e
commit 8232734216
2 changed files with 27 additions and 15 deletions

View File

@ -1066,20 +1066,25 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
}
fcx.demand_suptype(span, ret_ty, actual_return_ty);
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 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()));
},
_ => {},
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()));
},
_ => {},
}
}
}
}

View File

@ -203,12 +203,19 @@ 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() {
// we take the return type of the given main function, the real check is done
// in `check_fn`
actual.output().skip_binder()
} else {
// standard () main return type
tcx.mk_nil()
};
let se_ty = tcx.mk_fn_ptr(ty::Binder(
tcx.mk_fn_sig(
iter::empty(),
// the return type is checked in `check_fn`
actual.output().skip_binder(),
expected_return_type,
false,
hir::Unsafety::Normal,
Abi::Rust